1

So I've been using in-line (correct term?) ColdFusion code to run all my pages and have gotten to a point where I think I have a decent understanding of the basics, and want to take the next step. After a lot of cross-referencing, research, and trial and error, I've come up with the following 4 pages of which the intent is to be able to enter a username and password in the form page (crud.cfm), then, after submission, redirect the user to a page which displays the newly entered data, as well as any past entries.

I can do all of this with simple in-line code and an Application.CFM but I want to migrate toward a more OOP/Modular approach going forward, as presently I find myself rewriting/copy-pasting scads of code across several different pages. The error that I get when I submit from 'crud.cfm' is:

"The component attribute in cfinvoke tag has invalid value."

I have tried it without hashes and without the uppercase "A" to no avail. Here is my non-working code:

Application.cfc

<cfcomponent output="false"> <cffunction name="insertrecord" access="public" output="false"> <cfargument name="data" type="struct" required="true"> <cfquery name="create" datasource="test"> INSERT INTO logins( username, password) VALUES( 'trim(form.username)', 'trim(form.password)') </cfquery> </cffunction> </cfcomponent> 

crud.cfm

<h3> Enter new user/password </h3> <cfform name="thisform" method="post" action="procpage.cfm"> Username:<cfinput type="text" name="username" value=""> Password:<cfinput type="password" name="password" value=""> <input type="submit" value="submit"> </cfform> 

procpage.cfm

<cfif !StructIsEmpty(form)> <cfinvoke component="#Application#" method="insertrecord"> <cfinvokeargument name="data" value="#form#"> </cfinvoke> </cfif> <cflocation url="resultpage.cfm" addtoken="no"> 

resultpage.cfm

<cfquery name="read" datasource="test"> SELECT * FROM logins </cfquery> <table> <tr> <th>LOGIN</th> <th>USERNAME</th> <th>PASSWORD</th> </tr> <cfloop query="read"> <tr> <td>#read.login#</td> <td>#read.username#</td> <td>#read.password#</td> </tr> </cfloop> </table> 

ColdFusion version 8, MSSQL 2005 database. Thank you all in advance for your help, looking forward to your responses!

3
  • 1
    I think the main issue is that you have inserted your function "insertrecord" into Application.cfc. While this is allowed I think it will end up confusing you. I believe you are getting that error because you are referencing "#Application#" in your cfinvoke call. Application also happens to be a reserved word in ColdFusion for the Application scope. Just create a new .cfc file with your function in it and call that instead. Commented Mar 4, 2013 at 21:19
  • @Miguel-F Okay, so then with 'functions.cfc' in the dir (and now holding my insertrecord function) will CF server look for an 'Application.cfc' as well and/or is it required? Commented Mar 4, 2013 at 22:11
  • Yes, ColdFusion will automatically look for and execute (if found) the Application.cfc. Not only that, but there are specific events that you can define within the Application.cfc that fire during specific lifecycle events. It is very powerful. Read more about it here Commented Mar 5, 2013 at 13:23

2 Answers 2

2

Application.cfc is a special file in ColdFusion.

http://livedocs.adobe.com/coldfusion/8/htmldocs/help.html?content=AppEvents_01.html

You'll need to name your component something else. Application.cfc is where you put Application events, setup code, etc.

Sign up to request clarification or add additional context in comments.

Comments

1

In answer to your question to Miguel, Yes. The application.cfc is called each time a cfm is called. So when you hit the crud.cfm, application.cfc runs. When you hit procpage.cfm application.cfc runs etc..

so you want your procpage.cfm to look more like

<cfif !StructIsEmpty(form)> <cfinvoke component="functions" method="insertrecord"> <cfinvokeargument name="data" value="#form#"> </cfinvoke> </cfif> 

and your functions.cfc looks more like

<cfcomponent output="false"> <cffunction name="insertrecord" access="public" output="false" returntype="void"> <cfargument name="data" type="struct" required="true"> <cfquery name="create" datasource="test"> INSERT INTO logins( username, password) VALUES( <cfqueryparam cfsqltype="cf_sql_varchar" value="#trim(form.username)#">, <cfqueryparam cfsqltype="cf_sql_varchar" value="#trim(form.password)#"> ) </cfquery> </cffunction> <cffunction name="readRecord" access="public" returntype="query"> <cfargument name="loginID" type="numeric" required="false" default="0"> <cfquery name="read" datasource="test"> SELECT * FROM logins where loginID = <cfqueryparam cfsqltype="cf_sql_varchar" value="#arguments.loginID#"> </cfquery> <cfreturn read/> </cffunction> </cfcomponent> 

resultsPage.cfm

<cfscript> f = createObject('component','functions'); r= f.readRecord(theIdToPass); </cfscript> <table> <tr> <th>LOGIN</th> <th>USERNAME</th> <th>PASSWORD</th> </tr> <cfloop query="r"> <tr> <td>#r.login#</td> <td>#r.username#</td> <td>#r.password#</td> </tr> </cfloop> </table> 

You will find that cfqueryparam not only has a small performance boost but will protect you from sql attacks and such, USE IT!! Always.

You also might think about doing arguments for each one expect instead of using struct variables, since writting error trapping for a struct without know what you are expecting to be passed can be pretty frustrating.

Hopefully this can get you off to a positive start with CF!

2 Comments

thank you very much for the in-depth response and examples...yes I think this will go a long way toward my understanding of CF and also I had been meaning to start using cfqueryparam, but the online documentation oftentimes leaves a lot to be desired or is difficult for a novice to really comprehend what exactly is going on, so thank you for the example on that as well. Cheers! :)
No Problem @BrandonG Glad it was helpful. If you have a change can you mark this answer as accepted.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.