Это перепечатка поста в блоге, который я сделал 13 июня 2007 года. Я уже довольно давно пользуюсь этим методом, и он прекрасно работает! YMMV.
Кому не нравятся пользовательские функции (UDF)? Если вы занимались программированием, скорее всего, вы широко их использовали. Самая большая проблема, с которой сталкиваются люди, заключается в том, как включить и упорядочить их в вашем приложении.
Я обнаружил, что большинство людей создают Utils.cfc или UDFs.cfc, вырезая и вставляя свои UDF, которые они хотят использовать, в компонент, как показано ниже:
<!--- UDFs.cfc --->
<cfcomponent output="false">
<cffunction name="init" access="public” returntype="Any" output="false">
<cfreturn this>
</cffunction>
<cffunction name="myUDF1" access="public" returntype="Any" output="false">
</cffunction>
<cffunction name="myUDF2" access="public" returntype="Any" output="false">
</cffunction>
</cfcomponent>
После того как все пользовательские функции, которые ваше приложение будет использовать, вставлены в ваш компонент, вам нужно будет сделать эти пользовательские функции доступными для вашего приложения. Почти все, кого я видел, делают эту загрузку компонентом в область приложения. Следующая строка помещается в onApplicationStart()
, если вы используете Application.cfc или просто добавляете его в Application.cfm, если вы используете это:
<cfset application.functions = CreateObject("component", "udfs").init()>
Какой бы вы ни использовали, Application.cfc или Application.cfm, результаты будут одинаковыми; все ваши пользовательские функции доступны для вашего приложения, и вы можете свободно использовать их повсюду. Разница лишь в том, какое имя переменной вы используете. Я использую application.functions, некоторые используют application.utils или application.udfs; опять же, значения не имеют.
Есть одна проблема, с которой я столкнулся при таком подходе: он громоздкий и компонент UDFs станет огромным. Проблема, связанная с редактированием такого огромного файла компонента, становится кошмаром, поскольку прокрутка тысяч строк кода не очень интересна, а также я заметил, что CFEclipse заваливает огромные файлы. Конечно, свертывание кода дает некоторое облегчение, но должен быть лучший способ.
Я хотел, чтобы для каждого используемого UDF был только один файл, и чтобы приложение автоматически загружало их. Причиной этого было то, что если мне нужно было отредактировать myUDF1
, я мог бы просто открыть файл myUDF1.cfm
и отредактировать то, что мне нужно. Я также хотел иметь возможность получать пользовательские функции из CFLib.org и просто помещать их в мое приложение без необходимости что-либо редактировать. Если мне когда-нибудь понадобится удалить UDF из моего приложения, это будет так же просто, как удалить файл UDF и повторно инициализировать мое приложение.
Чтобы выполнить то, что я хотел, я изменил свой UDFs.cfc до 11 строк кода:
<!--- UDFs.cfc --->
<cfcomponent output="false">
<cfset variables.udfdir = GetDirectoryFromPath(GetCurrentTemplatePath()) & "udfs">
<cfset variables.q = "">
<cffunction name="init" access="public" returntype="Any" output="false">
<cfreturn this>
</cffunction>
<cfdirectory action="list" directory="#variables.udfdir#" filter="*.cfm" name="variables.q">
<cfoutput query="variables.q">
<cfinclude template="udfs\#name#">
</cfoutput>
</cfcomponent>
Так что именно происходит?
В двух словах, вот что происходит: у меня есть каталог с именем udfs
в том же каталоге, что и мой UDFs.cfc. Это каталог, в который я положил все свои файлы UDF CFM. UDFs.cfc выполняет сканирование этого каталога при его вызове и автоматически включает каждый найденный CFM-файл. Таким образом, он автоматически загружает любые UDF из папки UDF в себя (обычно это называется «mixin»).
Итак, моя цель достигнута! У меня есть каждый UDF в отдельном файле, поэтому мне не нужно пролистывать огромный файл компонента, чтобы найти его. Теперь я могу открыть и редактировать его легко. Глядя на каталог, я знаю, какие UDF использует мое приложение. Я могу автоматически добавить UDF из CFLib.org, просто сохранив текст из браузера в файл в каталоге. Кроме того, если мне больше не нужно использовать UDF в моем приложении, я просто удаляю файл из каталога, и он удаляется из моего приложения во время следующего повторного запуска. Все это делается без прикосновения к основному файлу UDFs.cfc.
Ниже приведен пример того, как выглядит один из файлов UDF CFM. Файл называется fullLeft.cfm
и находится в каталоге UDFs.
<!--- fullLeft --->
<cffunction name="fullLeft" access="public" displayname="fullLeft" returntype="string" output="false">
<cfargument name="str" type="string" required="true">
<cfargument name="count" type="numeric" required="true">
<cfif not refind("[[:space:]]", arguments.str) or (arguments.count gte len(arguments.str))>
<cfreturn Left(arguments.str, arguments.count)>
<cfelseif reFind("[[:space:]]",mid(arguments.str,arguments.count+1,1))>
<cfreturn left(arguments.str,arguments.count)>
<cfelse>
<cfif count-refind("[[:space:]]", reverse(mid(arguments.str,1,arguments.count)))>
<cfreturn Left(arguments.str, (arguments.count-refind("[[:space:]]", reverse(mid(str,1,arguments.count)))))>
<cfelse>
<cfreturn left(arguments.str,1)>
</cfif>
</cfif>
</cffunction>