ColdFusion - динамическое создание имен столбцов с помощью CFLOOP - PullRequest
2 голосов
/ 13 октября 2010

У меня есть таблица, в которой записываются названия загруженных документов, до 14 на запись. Столбцы названы так:

TABLE tblDocuments
COLUMNS documentID (int, not null, pk)
        document1 (varchar(250), null)
        document2 (varchar(250), null)
        /* and this continues through */
        document14 (varchar(250), null)

Поэтому я запрашиваю любые документы для конкретной записи:

<cfquery name="qryGetDocs" datasource="#dsn#">
     SELECT document1, ...document14
     FROM   tblDocuments
     WHERE  documentID = <cfqueryparam name="SESSION.documentID" cfsqltype="cf_sql_integer">
</cfquery>

Форма выглядит примерно так:

<form name="frmUploadDocs" method="post" action="documentsPage.cfm">

<input type="file" name="document1" size="50" >
<cfif qryGetDocs.document1 IS NOT ''>
   (current file name: <a href="#vars.file_path#/#qryGetDocs.document1#">#qryGetDocs.document1#</a>)</cfif>

<input type="file" name="document2" size="50" >
<cfif qryGetDocs.document2 IS NOT ''>
   (current file name: <a href="#vars.file_path#/#qryGetDocs.document2#">#qryGetDocs.document2#</a>)</cfif>

<!--- list all documents --->

<input type="file" name="document14" size="50" >
<cfif qryGetDocs.document14 IS NOT ''>
   (current file name: <a href="#vars.file_path#/#qryGetDocs.document14#">#qryGetDocs.document14#</a>)</cfif>

<input type="submit" name="submit" value="Upload Documents">
</form>

Я хочу выполнить цикл от 1 до 14, чтобы у меня был только один оператор <input> и <cfif>, например:

<cfloop from="1" to="14" index="i">
   <input type="fiile" name="document#i#" size="30">
   <cfif qryGetDocs.document#i# IS NOT ''>
     (current file name: <a href="#vars.file_path#/#qryGetDocs.document[#i#]#">#qryGetDocs.document[#i#]#</a>)
   </cfif>
</cfloop>

Однако я не могу получить правильный синтаксис независимо от того, что я пробовал. Может кто-нибудь, пожалуйста, помогите мне с этим? Спасибо!

Ответы [ 2 ]

3 голосов
/ 13 октября 2010

(На первоначальный вопрос уже был дан ответ. Но только для иллюстрации ...)

Более гибкая структура - хранить документы в виде строк.Таким образом, основная таблица может быть:

TABLE:    tblDocuments
COLUMNS:  DocumentID  (unique record id)
          UserID
          DocumentName

Используя эту структуру, вы можете извлечь все существующие документы для одного пользователя с помощью простого запроса

<cfquery name="qryGetDocs" datasource="#dsn#">
     SELECT documentID, documentName
     FROM   tblDocuments
     WHERE  userID = <cfqueryparam name="#SomeUserIDVariable#" cfsqltype="cf_sql_integer">
</cfquery>

.. и отобразить их с помощью простоговыходной цикл.(Обратите внимание, я добавил «documentID» в качестве скрытого поля для идентификации существующих документов ..)

<cfoutput query="qryGetDocs">
   ...
   <input type="file" name="document#CurrentRow#" size="50" >
   <input type="hidden" name="documentID#CurrentRow#" value="#documentID#" >
   (current file name: <a href="#vars.file_path#/#documentName#">#documentName#</a>)
</cfoutput>

Если запрос содержит менее 14 файлов (или любого другого максимального значения ..), вы можете использовать запрос.recordCount, чтобы определить, сколько дополнительных файлов вводить для отображения.

<cfset nextInputNumber = qryGetDocs.recordCount + 1>
<cfoutput>
<cfloop from="#nextInputNumber#" to="#MaximumNumberOfDocs#" index="counter">
   <input type="file" name="document#counter#" size="50" >
   <input type="hidden" name="documentID#counter#" value="0" >
</cfloop>
</cfoutput>
2 голосов
/ 13 октября 2010

Запросы могут быть доступны (например, структуры) с индексом строки и квадратными скобками, но только если вы также включите желаемый номер строки (!). Это работает как двумерный массив.

<cfloop from="1" to="14" index="i">
   <input type="file" name="document#i#" size="30">
   <cfif qryGetDocs["document#i#"][qryGetDocs.CurrentRow] IS NOT ''>
     (current file name: <a href="HTMLEditFormat("#vars.file_path#/#qryGetDocs["document#i#"][qryGetDocs.CurrentRow]#")#">#HTMLEditFormat(qryGetDocs["document#i#"][qryGetDocs.CurrentRow])#</a>)
   </cfif>
</cfloop>

Обратите внимание на HTMLEditFormat(), чтобы защитить себя от межсайтовых скриптовых атак. Это важно! Никогда не выводите данные в HTML, не удалив их должным образом. (Я допускаю, что имена файлов являются невероятным вектором атаки, потому что они обычно не могут содержать заостренные скобки, но а) вы не можете быть слишком осторожными, б) это хорошая привычка, и в) никто не знает, что такое безопасность дыры появятся, когда код будет пересмотрен в какой-то момент в будущем. Не HTML-экранирование данных - непростительная неряшливость.)

Более идиоматичная и гораздо более читаемая версия будет:

<cfloop from="1" to="14" index="i">
   <cfset RowNum  = qryGetDocs.CurrentRow>
   <cfset ColName = "document#i#">
   <cfset DocName = qryGetDocs[ColName][RowNum]> 
   <cfset DocPath = "#vars.file_path#/#DocName#">
   <input type="file" name="#ColName#" size="30">
   <cfif FileExists(ExpandPath(DocPath))>
     (current file name: <a href="#HTMLEditFormat(DocPath)#">#HTMLEditFormat(DocName)#</a>)
   </cfif>
</cfloop>
...