Questa è una ristampa di un blog post I did indietro il 13 giugno 2007. Ho utilizzato questo metodo per un bel po 'e funziona benissimo! YMMV.
A chi non piacciono le funzioni definite dall'utente (UDF)? Se hai fatto qualche programmazione, è probabile che tu li abbia usati ampiamente. Il problema più grande che le persone hanno con loro è come includerli e organizzarli nella tua applicazione.
Quello che ho trovato che la maggior parte della gente è creare un Utils.cfc o UDFs.cfc e tagliare e incollare le loro UDF che vogliono utilizzare nel componente come illustrato di seguito:
<!--- 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>
volta avere tutte le UDF che l'applicazione utilizzerà incollata nel componente, sarà necessario rendere disponibili le UDF alla propria applicazione. Quasi tutti quelli che ho visto eseguono questo caricamento dal componente nello scope dell'applicazione. La riga seguente è inserito nel onApplicationStart()
se si sta utilizzando Application.cfc o semplicemente aggiungendolo nella Application.cfm se si sta utilizzando che:
<cfset application.functions = CreateObject("component", "udfs").init()>
Qualunque sia uno che si sta utilizzando, Application.cfc o Application.cfm, i risultati sono gli stessi; tutte le tue UDF sono disponibili per la tua applicazione e puoi utilizzarle liberamente. L'unica differenza è quale nome di variabile usi. Uso le funzioni di applicazione, alcuni usano application.utils o application.udfs; non importa, di nuovo, i risultati sono gli stessi.
C'è un problema che ho con questo approccio, però, è ingombrante e il componente UDF diventerà enorme. Il problema di avere un file componente così grande è la modifica diventa un incubo poiché scorrere migliaia di righe di codice non è molto divertente e ho anche notato che CFEclipse si blocca su file enormi. Il collasso del codice sicuro fornisce un certo sollievo, ma deve esserci un modo migliore.
Quello che volevo era avere un solo file per ogni UDF che stavo usando e un modo per la mia applicazione di caricarli automaticamente. La ragione di questo era che se avessi avuto bisogno di modificare myUDF1
, avrei potuto semplicemente aprire il file myUDF1.cfm
e modificare quello che mi serviva. Volevo anche essere in grado di catturare UDF da CFLib.org e semplicemente rilasciarli nella mia applicazione senza dover modificare nulla. Se dovessi rimuovere una UDF dalla mia applicazione, sarebbe facile come cancellare il file UDF e reinizializzare la mia applicazione.
per realizzare quello che volevo, ho modificato il mio UDFs.cfc a 11 righe di codice:
<!--- 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>
Così che cosa esattamente sta succedendo?
In breve, ecco cosa sta succedendo: ho una directory denominata udfs
nella stessa directory in cui ho il mio UDFs.cfc. Questa è la directory in cui ho inserito tutti i miei file UDF CFM. Ciò che fa UDFs.cfc è la scansione di questa directory quando viene chiamata e include automaticamente ogni file CFM che trova. In questo modo carica automaticamente tutte le UDF nella cartella UDF in sé (comunemente chiamata "mixin").
Quindi il mio obiettivo è raggiunto! Ho ciascuna UDF nel proprio file, quindi non devo scorrere un enorme file componente per trovarlo. Ora posso aprirlo e modificarlo facilmente. Guardando la directory, so quali sono le UDF utilizzate dalla mia applicazione. Posso aggiungere automaticamente una UDF da CFLib.org semplicemente salvando il testo dal browser in un file nella directory. Inoltre, se non ho più bisogno di usare l'UDF nella mia applicazione, semplicemente cancello il file dalla directory e viene rimosso dalla mia applicazione durante il prossimo re-init. Tutto ciò viene fatto senza dover toccare il file UDFs.cfc principale.
Di seguito è riportato un esempio di come si presenta uno dei file CFM UDF. Il file si chiama fullLeft.cfm
e risiede nella directory UDF.
<!--- 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>
Idea molto interessante, dovrò sperimentare il tuo approccio. – kevink
Lo sto facendo da molto tempo con buoni risultati. –
L'ho implementato ieri e devo dire che ha funzionato benissimo. Ho anche utilizzato l'approccio per semplificare i miei test unitari eseguendo il looping della directory, assicurando così che nessuna funzione possa essere ignorata. Molto lucido – kevink