 |
Wanneer u start met ColdFusion
programmeren is het nog niet zo belangrijk: hergebruik van code.
Op basis van een idee maakt u een ontwerp. Op grond van het ontwerp
begint u te bouwen.
Tot zover: niets aan de hand. |
| |
|
Gaandeweg de tijd breidt de applicatie (en het ontwerp) zich uit
en wordt er steeds meer functionaliteit in betrokken. Het aantal
cfm-pagina's neemt toe en de applicatie groeit voorspoedig.
Totdat... U het gevoel krijgt dat u spaghetti aan het programmeren
bent en iemand uit uw omgeving (misschien) subtiel informeert of
CF ook 'modules' kent waarmee steeds weerkerende functies
centraal afgehandeld kunnen worden.
Dit overkwam mij nog niet zo lang geleden.
Een (al bestaande) webapplicatie van één van onze
klanten moest uitgebreid worden met aanzienlijk wat functionaliteit
- die bovendien ook nog eens toegekend moest worden aan verschillende
gebruikersgroepen, met ieder weer zijn/haar eigen autorisatieregels.
Tijdens de verbouw ontdekten we dat we dezelfde code - copy, paste
- op verschillende plekken in de applicatie steeds opnieuw gebruikten.
Niet handig natuurlijk, want: stel dat deze code (op applicatieniveau
en in de toekomst) ooit nog eens verandert moest worden.
Aldus de subtiel gestelde vraag.
Kent CF functionaliteit waarbij 1x geschreven code aangesproken
(en hergebruikt) kan worden vanuit andere cfm-pagina's? "Modules",
zoals PHP die kent, of: "Objecten" zoals Java ze kent?
CFC's!
ColdFusion Componenten
ColdFusion Componenten (CFC's) zijn nieuw in Macromedia ColdFusion
MX.
CFC's maken gestructureerde applicatieontwikkeling mogelijk. Inderdaad:
vergelijkbaar met "Modules" uit PHP of "Objecten"
uit Java - maar, kenmerkend voor ColdFusion - zonder de complexiteit
ervan!
Kort gezegd is een CFC niets anders dan een gewone CFML pagina,
waarin één of meer functies opgesloten zitten
die - ieder individueel - aangeroepen kunnen worden vanuit andere
CFML pagina's en - op zijn beurt - aan de aanroepende pagina een
verwerkingsresultaat terug kan geven.

Het 'principe' van CFC's...
Het gegeven dat een CFC meerdere functies kan bevatten die
ieder afzonderlijk aangeroepen kunnen worden, maakt dat een
CFC ook wezenlijk 'iets anders' is dan een 'ColdFusion Custom tag',
waarvan de inhoud slechts steeds in zijn geheel aangeroepen
en verwerkt kan worden.
Om een praktisch voorbeeld te geven:
- indien u in uw applicatie bepaalde database queries (add, update,
delete, get) in verschillende pagina's steeds opnieuw 'hard' codeert,
zijn deze queries potentiële kandidaten om in een
CFC weg te zetten.
- Indien u gebruik maakt van steeds dezelfde verificatieprocedures,
dan zijn dat eveneens kandidaten voor een CFC.
CFC's ontwikkelen
Nu u weet wat CFC's zijn, kijken we
hoe u ze maakt.
Om een CFC te creëren zijn maar twee stappen nodig (en maar
één, indien u Dreamweaver MX gebruikt).
1. Creëer een bestand met de extensie .cfc (ter onderscheid
van .cfm: de bestandextensie voor uw 'gewone' ColdFusion
pagina's)
2. Voer vier nieuwe CF-tags in:
<CFCOMPONENT>, om het CFC-bestand te definiëren;
<CFFUNCTION>, om de functie ('methode') te definiëren;
<CFARGUMENT>, om eventueel van buitrenaf meegegeven argumenten
(parameters) in de functie te accepteren;
<CFRETURN>, om het resultaat van de functie in op te slaan
en terug te geven aan de aanvragende .cfm pagina.
Buiten deze tags kunt u in CFC's willekeurig elke andere CF-tag
gebruiken. CFC's verschillen wat dat betreft niet zoveel van 'normale'
CFML-pagina's. Mocht het wat esoterisch klinken, een voorbeeld:
CFC: de praktijk
1. Open Dreamweaver MX en selecteer File > New
2. Selecteer in het dialoogscherm New Document de optie: Dynamic
Page > ColdFusion Component en klik op de knop 'Create'.
In Codeview genereert Dreamweaver de volgende code:
<CFCOMPONENT>
<CFFUNCTION name="myFunction"
access="public" returntype="string">
<CFARGUMENT name="myArgument"
type="string" required="true">
<CFSET myResult="foo">
<CFRETURN myResult>
</CFFUNCTION>
</CFCOMPONENT>
<CFCOMPONENT></CFCOMPONENT> geeft het begin en het eind van de CFC-pagina aan - zoals <HTML> </HTML>
het begin en einde aangeeft van een normale HTML-pagina - .
<CFFUNCTION></CFFUNCTION> geeft - op dezelfde
manier - het begin en eind van een functie aan.
Binnen CFC's kunnen meerdere functies opgenomen worden die
ieder, via hun NAME attribuut van buitenaf benadert kunnen worden.
<CFFUNCTION> kent 5 attributen, waarvan Dreamweaver er drie
voor u klaar zet:
- Name: voor de naam van de functie. Met behulp van deze
naam wordt de functie zodadelijk van buitenaf aangesproken. De
naam van een functie moet, binnen een CFC, daarom ook uniek zijn!
- Access: bepaalt de toegang tot deze functie. De opties
zijn: "private", "pacage", "public"
en "remote".
- ReturnType: geeft het gegevenstype aan, dat aan de aanroepende
pagina geretourneerd moet worden. Opties zijn: string, …,
query.
De <CFARGUMENT> tag informeert de functie over eventueel
vanuit de aanroepende pagina meegegeven variabelen. Strikt genomen
is <CFARGUMENT> alleen nodig indien van een dergelijke variabele
sprake is en kunt u dus weglaten, als dat niet zo is!
<CFRETURN> tenslotte retourneert het resultaat van de functie terug naar de aanroepende CFML-pagina.
In dit voorbeeld creëren we een CFC waarin een datum gegenereerd
wordt, vervolgens omgezet wordt naar de Nederlandse notatie en terug
gegeven wordt aan de aanvragende CFML-pagina:
1. Verander in de code de CFFUNCTION name in:
<CFFUNCTION name="myDatumFunction">
2. Haal de regel met <CFARGUMENT> weg. In dit voorbeeld heeft
u die niet nodig.
3. Plaats de cursor voor <CFSET myResult="foo">
en toets op Enter om een witregel toe te voegen.
4. Maak een <CFSET> aan met de variabelenaam myDatum en de volgende waarde:
<CFSET myDatum=CreateODBCDate(now())>
5. Vervang <CFSET myResult="foo"> met een datum-Format
waarmee de datumvariabele in een Nederlandse notatie wordt omgezet:
<CFSET oldlocale = SetLocale("Dutch (Standard)")>
<CFSET myResult = LSDateFormat(NOW(), "DDDD, DD MMMM YYYY")>
6. Vervang <CFRETURN myResult> met:
<CFRETURN myDatumResult>
7. Uw functie zou er nu als volgt uit moeten zien:
<CFFUNCTION name="myDatumFunction" access="public"
returntype="string">
<CFSET myDatum=CreateODBCDate(now())>
<CFSET oldlocale = SetLocale("Dutch (Standard)")>
<CFSET myDatumResult = LSDateFormat(myDatum,
"DDDD, DD MMMM YYYY")>
<CFRETURN myDatumResult>
</CFFUNCTION>
8. Sla het bestand op als myCFC.cfc
Gebruik van CFC's vanuit andere CFML-pagina's
Nu u uw CFC gecreëerd heeft kunt u deze functie in uw andere
CFML-pagina's oproepen en gebruiken.
Om vanuit een CFML-pagina een functie binnen een CFC te bereiken
gebruikt u <CFINVOKE>.
<CFINVOKE> is een nieuwe tag in CFMX. Eén van haar
taken is om ColdFusion Componenten (en de functie daarin) op te
roepen en te activeren.
9. Maak in Dreamweaver MX een nieuwe (gewone) CFML pagina aan en
sla deze op als test_cfc.cfm.
10. Switch naar Codeview en voer de volgende code in:
<CFINVOKE COMPONENT="myCFC"
METHOD="myDatumFunction"
RETURNVARIABLE="myDatumResult">
</CFINVOKE>
In COMPONENT wordt het .cfc bestand (het ColdFusion Componentenbestand)
aangeroepen. In ons voorbeeld is dat: myCFC.cfc (maar hier
dan zonder de extensie!).
In METHOD wordt de functie aangegeven, die binnen
dat bestand benaderd (en uitgevoerd) moet worden.
In RETURNVARIABLE wordt de naam van de variabele gedeclareerd,
die de gegevens bevat van wat de functie aan deze pagina ook maar
moet retourneren.
11. Plaats tenslotte ergens onder het <CFINVOKE>-blok een
<CFOUTPUT> tag, waarin variabele myDatumResult op het scherm
zichtbaar wordt gemaakt:
<CFOUTPUT>#myDatumResult#</CFOUTPUT>
Het geheel moet er dan alsvolgt uit zien:
<HTML>
<HEAD>
<TITLE>Untitled Document</TITLE>
<META http-equiv="Content-Type" content="text/html;
charset=iso-8859-1">
</HEAD>
<BODY>
(Roept myCFC.cfm op en genereert een datum!)
<P></P>
<CFINVOKE component="myCFC"
method="myDatumFunction"
returnvariable="myDatumResult">
</CFINVOKE>
<B>Vandaag is het:</B> <CFOUTPUT>#myDatumResult#</CFOUTPUT>
</BODY>
</HTML>
12. Sla het bestand op als test_cfc.cfm en toets op F12
om de uitvoer te testen.
U zou zoiets moeten zien als:
Vandaag is het: zondag, 15 februari 2004
Variabelen doorgeven aan een CFC
Na dit voorbeeld is het niet moeilijk meer om een riedeltje code
te schrijven waarin een variabele doorgegeven wordt aan de
functie. Tegelijk maken we dit voorbeeld wat gecompliceerder door
in de functie een database query op te nemen.
1. Open myCFC.cfc.
2. Voeg onder de bestaande datum <CFFUNCTION> (maar nog boven
de </CFCOMPONENT>) de volgende code toe:
<CFFUNCTION name="myGamesZoekFunction" access="public"
returntype="query">
<CFQUERY NAME = "games_zoek" DATASOURCE
= "GamesOnline">
SELECT GameId,
Titel, Categorie, Uitgever, Beschikbaarheid, Platform, VerschijningsDatum
FROM tblGames
WHERE Categorie
= '#Form.Categorie#'
</CFQUERY>
<CFRETURN games_zoek>
</CFFUNCTION>
Zoals u ziet bestaat deze functie uit een gewone query - in dit
geval een zoekopdracht op een tabel met computergames, waarbij gezocht
wordt op een bepaalde spelcategorie en waar uit verschillende velden
gegevens getrokken worden.
Als returntype is hier nu gedefinieerd: "query".
3. Open in Dreamweaver een nieuwe .cfm pagina en voeg daarin
onderstaande code toe:
<FORM action="zoek_cfc_Action.cfm" method="post">
<B>Zoek</B>:
<INPUT type="text"
name="Categorie" >
<BR><BR>
<INPUT name="submit"
type="submit" value="Nu zoeken">
</FORM>
De FORM-action verwijst naar de verwerkingspagina, die u zodadelijk
gaat maken.
4. Sla dit bestand op als zoek_cfc.cfm.
5. Open nog een nieuw .cfm bestand om de verwerkingspagina te maken.
Voer onderstaande code in:
<CFINVOKE component="myCFC"
method="myGamesZoekFunction"
returnvariable="games_zoek">
</CFINVOKE>
In <CFINVOKE> wordt (opnieuw) myCFC.cfm opgeroepen, nu specifiek
gericht op de functie myGamesZoekFunction.
De resultaten uit CFC komen terecht in de returnvariable games_zoek.
Deze kunt in een CFOUTPUT query gebruiken om de uiteindelijke resultaten
van deze zoekopdracht op het scherm te krijgen:
<CFOUTPUT query="games_zoek">
#Titel#, #Categorie#, #Uitgever#
<BR>
</CFOUTPUT>
Sla het bestand op als zoek_cfc_Action.cfm.
Voor zover u de beschikking heeft over de GamesOnline database
uit 'Leer jezelf PROFESSIONEEL… ColdFusion MX' kunt
u deze code testen. Als uitvoer zou u zoiets moeten krijgen als:
Resultaat van uw zoekopdracht:
Baldur's Gate, RPG , Biowhere
Lionhart, RPG , Interpay
Darkstone, RPG , Delfine Software
Baldur's Gate II: Shadows of Amn, RPG , Biowhere
Baldur's Gate II: Throne of Bhaal, RPG , Biowhere
Divine Divinity, RPG , Hilarian Studios
Final Fantasy XI, RPG , Roundsoft
EverQuest: Shadows of Luclin, RPG , Sunny
Neverwinter Nights, RPG , Biowhere
Neverwinter Nights: Shadows of Undrentide, RPG , Biowhere
Mocht u niet beschikken over de database, is het voor u vanaf
nu een eitje om dit voorbeeld in andere situaties toe te
passen.
De pro's van CFC's
Nu u in kort bestek gezien heeft wat u met CFC's kunt, blijft
over: waarom?
- De meeste ColdFusion ontwikkelaars gebruiken meerdere technieken
in hun applicaties: database queries, HTML, Javascript, 'bussiness
logic' en meer. Het is goed, waar mogelijk, content van presentatie te scheiden.
CFC's maken die scheiding mogelijk.
- CFC maakt het mogelijk voor grafische ontwikkelaars GUI's te
ontwerpen zonder daarbij direct betrokken te hoeven zijn bij de
data laag - die voor rekening komt van databaseontwerpers.
- En: omdat functies in CFC's 'gecentraliseerd' zijn maakt dit
de applicatieontwikkeling en onderhoudbaarheid ervan aanzienlijk
eenvoudiger.
Als u CFC's op de correcte manier schrijft zijn ze zelfs toepasbaar
voor andere code dan CFML: Flash Remoting, webservices (SOAP) en
mobiele communicatie. Mits u CFC's op een correcte manier
gebruikt. (Maar meer daarover op een later tijdstip.)
Informatie over CFC's vindt u ondermeer op DevNet van Macromedia.
|