ColdFusion Forms - mysql

I'm trying to make a form that accesses a MySQL database. But all of this is new to me. I think I might be trying to reach too far beyond my basic understanding of this. Here is my question.
I have a form. In this form I have the connection made to the database and am able to post to the database. What I'm trying to do is have an option field with "tile 1", "tile 2", "tile 3". For each "tile" I'd like to have the rest of the fields saved under that tile ID. I'd also like to be able to pull that tiles information when selecting the tile from the option field.
Here is my current code. Please keep in mind I'm new to all of this. Thanks.
Form:
<cfform method="post" name="TileAdAdmin" action="index.cfm">
<cfoutput>
<table width="500px">
<tr>
<td height="159"><label class="labelStyle">Tile Ads</label></td>
<td>
Tile Number:<select name="TAID" id="TAID">
<option value="0">None</option>
<option value="1">Tile 1</option>
<option value="2">Tile 2</option>
<option value="3">Tile 3</option>
</select><br /><br />
Headline:
<input name="TAHL" type="text" id="TAHL" title="TAHL" value="#variables.ta.TAHL#" maxlength="30" />
<br />
Image Name:
<input name="TAImage" type="text" id="TAImage" title="TAImage" value="#variables.ta.TAImage#" maxlength="30" />
<br />
Discription:
<textarea name="TADiscription" cols="30" rows="6" id="TADiscription" title="VimeoID">#variables.ta.TADiscription#</textarea> <br />
</td>
</tr>
</table><br />
<input type="hidden" value="#variables.controller#" name="controller">
<input type="hidden" value="#variables.action#" name="action">
<input type="Submit" value="Submit" name="Submit" class="formInput">
</cfoutput>
</cfform>
DAO Code:
<cfcomponent name="TADAO" displayname="" hint="" output="false">
<cffunction name="read" access="public" returntype="Void" output="false" hint="CRUD method">
<cfargument name="ta" type="ta" required="yes" />
<cfset var qRead = 0 />
<cfquery name="qRead" datasource="#Application.dbsource#" >
SELECT
TAID,
TAHL,
TAIMAGE,
TADISCRIPTION
FROM
T026_TILE_ADS
</cfquery>
<cfif qRead.RecordCount>
<cfset arguments.ta.setTAID(qread.TAID) />
<cfset arguments.ta.setTAHL(qread.TAHL) />
<cfset arguments.ta.setTAImage(qread.TAIMAGE) />
<cfset arguments.ta.setTADiscription(qread.TADISCRIPTION) />
<cfelse>
<cfthrow type="emptyRecordset" errorcode="TADAO.read.emptyRecordset" message="Unable to locate the TILE_AD data record." />
</cfif>
</cffunction>
<cffunction name="update" access="public" returntype="Void" output="false" hint="CRUD method">
<cfargument name="TA" type="TA" required="yes" />
<cfquery name="qUpdate" datasource="#Application.dbsource#">
UPDATE
T026_TILE_ADS
SET
TAID = <cfqueryparam cfsqltype="cf_sql_numeric" value="#arguments.ta.getTAID()#" />,
TAHL = <cfqueryparam cfsqltype="cf_sql_varchar" value="#arguments.ta.getTAHL()#" />,
TAIMAGE = <cfqueryparam cfsqltype="cf_sql_varchar" value="#arguments.ta.getTAImage()#" />,
TADISCRIPTION = <cfqueryparam cfsqltype="cf_sql_text" value="#arguments.ta.getTADiscription()#" />
</cfquery>
</cffunction>
</cfcomponent>
Component code:
<cfcomponent displayname="ta" hint="" output="false">
<cfproperty name="TAID" displayname="" type="numeric" />
<cfproperty name="TAHL" displayname="" type="string" />
<cfproperty name="TAImage" displayname="" type="string" />
<cfproperty name="TADiscription" displayname="" type="string" />
<cffunction name="init" access="public" returnType="TA" output="false" hint="">
<cfset this.TAID = 0 />
<cfset this.TAHL = "headline" />
<cfset this.TAImage = "IMAGE" />
<cfset this.TADiscription = "Discription" />
<cfreturn this />
</cffunction>
<cffunction name="getTAID" access="public" output="false" returntype="numeric">
<cfreturn this.TAID />
</cffunction>
<cffunction name="setTAID" access="public" output="false" returntype="void">
<cfargument name="TAID" type="numeric" required="true" />
<cfset this.TAID = arguments.TAID />
<cfreturn />
</cffunction>
<cffunction name="getTAHL" access="public" output="false" returntype="string">
<cfreturn this.TAHL />
</cffunction>
<cffunction name="setTAHL" access="public" output="false" returntype="void">
<cfargument name="TAHL" type="string" required="true" />
<cfset this.TAHL = arguments.TAHL />
<cfreturn />
</cffunction>
<cffunction name="getTAImage" access="public" output="false" returntype="string">
<cfreturn this.TAImage />
</cffunction>
<cffunction name="setTAImage" access="public" output="false" returntype="void">
<cfargument name="TAImage" type="string" required="true" />
<cfset this.TAImage = arguments.TAImage />
<cfreturn />
</cffunction>
<cffunction name="getTADiscription" access="public" output="false" returntype="string">
<cfreturn this.TADiscription />
</cffunction>
<cffunction name="setTADiscription" access="public" output="false" returntype="void">
<cfargument name="TADiscription" type="string" required="true" />
<cfset this.TADiscription = arguments.TADiscription />
<cfreturn />
</cffunction>
<cffunction name="dump" access="public" output="true" returntype="void">
<cfoutput>
Tile: #this.TAID# <br />
Headline: #this.TAHL# <br />
Image: #this.TAImage# <br />
Description: #this.TADiscription# <br />
</cfoutput>
</cffunction>

TAID as a primary key
TAID is the identifier of each of your tiles, so first of all you need to add it to a WHERE clause in the SQL statements.
UPDATE
T026_TILE_ADS
SET
TAHL = <cfqueryparam cfsqltype="cf_sql_varchar" value="#arguments.ta.getTAHL()#" />,
TAIMAGE = <cfqueryparam cfsqltype="cf_sql_varchar" value="#arguments.ta.getTAImage()#" />,
TADISCRIPTION = <cfqueryparam cfsqltype="cf_sql_text" value="#arguments.ta.getTADiscription()#" />
WHERE
TAID = <cfqueryparam cfsqltype="cf_sql_numeric" value="#arguments.ta.getTAID()#" />
SELECT
TAID,
TAHL,
TAIMAGE,
TADISCRIPTION
FROM
T026_TILE_ADS
WHERE
TAID = <cfqueryparam cfsqltype="cf_sql_numeric" value="#arguments.ta.getTAID()#" />
Calling the update query before the select query
Update: after analysing your database code, the order of definition of cfquerys is not important since they are inside CFFUNCTIONS of the CFCOMPONENT.
Selecting OPTION with Jquery
Finally you will need to select the tile from the submitted form, you can spice your code with Jquery (add inside, at the end of the CFOUTPUT)
<!--- (beginning of CFOUTPUT ...) --->
<input type="Submit" value="Submit" name="Submit" class="formInput">
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.5/jquery.min.js"></script>
<script>
$(document).ready(function(){
$('SELECT##TAID').val(#variables.ta.TAID#);
});
</script>
</cfoutput>
Edit 26/07
Using <CFSELECT> instead
In the CFOUTPUT the TAID field is a simple HTML SELECT. Since we want to pull records from the DB, try this:
Put before the CFOUTPUT tag:
<cfquery name="qryTiles" datasource="#Application.dbsource#">
SELECT
TAID,
TAHL,
TAIMAGE,
TADISCRIPTION
FROM
T026_TILE_ADS
</cfquery>
And replace:
<select name="TAID" id="TAID">
<option value="0">None</option>
<option value="1">Tile 1</option>
<option value="2">Tile 2</option>
<option value="3">Tile 3</option>
</select>
with:
<cfselect name="TAID"
size=1
multiple="no"
query="qryTiles"
value="TAID"
display="TAID"
queryPosition="below">
<option value="0">None</option>
</cfselect>

Related

What is the correct way to use sql query in coldfusion function

I have this code that will passed variable to function and insert it. But I'm getting error:
<cffunction name="insertSupplierPersonnel" output="false" access="public" returnType="struct">
<cfargument name="name" type="string" required="true" />
<cfargument name="email" type="string" required="false" default="" />
<cfargument name="office_phone" type="string" required="false" default="" />
<cfargument name="mobile_phone" type="string" required="false" default="" />
<cfargument name="designation" type="string" required="false" default="" />
<cfset var res = '' />
<cfquery datasource="#session.dsn_aset#" result="res">
INSERT INTO `supplier_personnel_incharge` (
`name`,
`email`,
`office_phone`,
`mobile_phone`,
`designation`
)
VALUES
(
cfargument.name,
cfargument.email,
cfargument.office_phone,
cfargument.mobile_phone,
cfargument.designation
) ;
</cfquery>
<cfreturn res />
</cffunction>
<cfset res = insertSupplierPersonnel(name='#form.personnel_name#', email='#form.personnel_email#', office_phone='#form.personnel_office_phone#', mobile_phone='#form.personnel_mobile_phone#', designation='#form.personnel_designation#') />
<cfdump var="#res#">
I'm getting this error:
There's a problem with cfargument.name. What is the correct way to use cfargument for insert query? Thanks in advance.
First, the correct scope is arguments, not cfargument. So, change this sort of thing:
cfargument.name,
to this:
arguments.name,
Next, you have to surround your variable names with pound signs to get the value of the variable, i.e. #arguments.name#.
Next, use query parameters, i.e. <cfqueryparam value="#arguments.name#">. Among other things, they will escape special characters used in the SQL query syntax.
To summarize all of the correct answers and comments above. This would be your best practice:
Function returnType should be "query", not "struct"
If you specify a default value, CF recognizes the argument as "not required"
Use cfqueryparam on all query parameters
Optional
Use the null attribute of cfqueryparam to insert a NULL if there is no value given
You don't need a trailing semi-colon at the end of the sql statement
<!---return type is query, not struct --->
<cffunction name="insertSupplierPersonnel" output="false" access="public" returnType="query">
<cfargument name="name" type="string" required="true" />
<!--- NOTE: If you specify a default value, CF recognizes the argument as "not required" --->
<cfargument name="email" type="string" default="" />
<cfargument name="office_phone" type="string" default="" />
<cfargument name="mobile_phone" type="string" default="" />
<cfargument name="designation" type="string" default="" />
<cfquery datasource="#session.dsn_aset#" result="local.data">
INSERT INTO supplier_personnel_incharge (
name, /*Unless your database column names are case-sensitive, you don't need quotation marks around the column names*/
email,
office_phone,
mobile_phone,
designation
)
VALUES
(
<cfqueryparam cfsqltype="cf_sql_varchar" value="#trim(arguments.name)#">,
/*insert NULL if there is no value given*/
<cfqueryparam cfsqltype="cf_sql_varchar" null="#Not Len(trim(arguments.email))#" value="#trim(arguments.email)#">,
<cfqueryparam cfsqltype="cf_sql_varchar" null="#Not Len(trim(arguments.office_phone))#" value="#trim(arguments.office_phone)#">,
<cfqueryparam cfsqltype="cf_sql_varchar" null="#Not Len(trim(arguments.mobile_phone))#" value="#trim(arguments.mobile_phone)#">,
<cfqueryparam cfsqltype="cf_sql_varchar" null="#Not Len(trim(arguments.designation))#" value="#trim(arguments.designation)#">,
) /*you don't need a trailing semi-colon*/
</cfquery>
<cfreturn local.data />
</cffunction>
<cfset local.res = insertSupplierPersonnel(name='#form.personnel_name#',
email='#form.personnel_email#',
office_phone='#form.personnel_office_phone#',
mobile_phone='#form.personnel_mobile_phone#',
designation='#form.personnel_designation#') />
<cfdump var="#local.res#">

cffunction: second argument based on first argument

I have following code that first creates an object and afterwards it calls a function called init.
<cfset SESSION.objWatchlist = createObject("component", "path") />
<cfset SESSION.objWatchlist.init(session.addressid) />
So far so good. The init function looks like this:
<cffunction name="init" access="remote" output="false">
<cfargument name="addressID" type="numeric" required="true" />
<cfset THIS.ADDRESSID = arguments.addressID />
<cfset THIS.WATCHLIST = arrayNew(1) />
<cfset initWatchlistArray() />
<cfreturn this />
</cffunction>
Now I want to add another argument to the cffunction. I will call it like this:
<cfset SESSION.objWatchlist.init("addressid", session.addressid) />
and
<cfset SESSION.objWatchlist.init("sessionid", session.sessionid) />
I add some new lines in the cffunction:
<cffunction name="init" access="remote" output="false">
<cfargument name="typeOfID" type="string" required="true" />
<cfif arguments.typeOfID eq "addressid">
<cfargument name="addressID" type="numeric" required="true" />
<cfset THIS.ADDRESSID = arguments.addressID />
<cfelseif arguments.typeOfID eq "sessionid">
<cfargument name="sessionID" type="string" required="true" />
<cfset THIS.SESSIONID = arguments.sessionID />
</cfif>
<cfset THIS.WATCHLIST = arrayNew(1) />
<cfset initWatchlistArray() />
<cfreturn this />
</cffunction>
But everytime I get the error "The tag must be nested inside a CFFUNCTION tag".
Now my question is how can I write a function in which the second argument is based on the first one?
Is this even possible?
Thank you.
At the end I have found a solution that looks like that:
First I call the function:
<cfset SESSION.objWatchlist.init(addressID=session.addressid) />
<cfset SESSION.objWatchlist.init(sessionID=session.sessionid) />
I changed the function to following:
<cffunction name="init" access="remote" output="false">
<cfargument name="addressID" type="numeric" required="false" />
<cfargument name="sessionID" type="string" required="false" />
<cfif isDefined("arguments.addressid")>
<cfset THIS.ADDRESSID = arguments.addressID />
<cfelseif isDefined("arguments.sessionid")>
<cfset THIS.SESSIONID = arguments.sessionid />
</cfif>
<cfset THIS.WATCHLIST = arrayNew(1) />
<cfset initWatchlistArray() />
<cfreturn this />
</cffunction>
When calling the function I can call them with the name of the argument in the cffunction.
Afterwards I can check which one is defined.
This is too long for a comment, but I have a little cleanup on this
SESSION.objWatchlist.init(addressID=session.addressid);
SESSION.objWatchlist.init(sessionID=session.sessionid);
any function init(numeric addressID, string sessionid) access="remote" output="false" {
if (arguments.keyexists(("addressid")) { THIS.ADDRESSID = arguments.addressID; }
else if (arguments.keyexists("sessionid") { THIS.SESSIONID = arguments.sessionid; }
THIS.WATCHLIST = [];
initWatchlistArray();
return this;
}
Note: the use of .keyexists(). This is a faster check because it does not have to look through every scope that could have something that matches.
Also note it is easier to blank out an array.

Output HTML from XML in ColdFusion

I have a query running to gather an adjacency list and then generate an XML object of that list as a tree. Next I need to output that tree as a simple HTML.
I would like my output of XML document to be:
<ul>
<li margin="5">Title
<ul>
<li margin="10">Title</li>
</ul>
</li>
</ul>
Here is what I have coded so far:
<cfquery name="nodeTable" datasource="#database.ds#">
SELECT [mc_location].[id],[mc_location].[title], [mc_location].[parent_id] FROM [mc_location]
LEFT JOIN [mc_location_type] ON [mc_location].[id] = [mc_location_type].[location_id]
WHERE [mc_location_type].[category] = 'staff'
</cfquery>
<cffunction name="outputChildNodes" access="public" returntype="void" output="true">
<cfargument name="nodeTable" type="query" required="true" hint="I am the node query object."/>
<cfargument name="parent_id" type="numeric" required="false" default="0"/>
<cfset var local = {}/>
<cfquery name="local.childNodes" dbtype="query">
SELECT id, parent_id, title
FROM arguments.nodeTable
WHERE parent_id = <cfqueryparam value="#arguments.parent_id#" cfsqltype="cf_sql_integer" />
ORDER BY id ASC
</cfquery>
<cfloop query="local.childNodes">
<child id="#local.childNodes.id#" parent-id="#local.childNodes.parent_id#" name="#local.childNodes.title#">
<cfset outputChildNodes(arguments.nodeTable, local.childNodes.id)/>
</child>
</cfloop>
<cfreturn/>
</cffunction>
<!--- Build the node XML document recursively. --->
<cfxml variable="nodeTree">
<childern>
<!--- Output the root-level nodes. --->
<cfset outputChildNodes( nodeTable ) />
</childern>
</cfxml>
<!--- Render the XML document. --->
<cfloop index="childern" array="#nodeTree.childern#">
<cfloop index="child" array="#childern#">
<cfif isStruct(child.XmlAttributes)>
<cfdump var="#child[1].XmlAttributes#"/>
</cfif>
</cfloop>
</cfloop>
Thank you!
The problem I was experiencing had to do with not properly defining variable scopes (e.g. using "var" in cfset, using arguments.parameter, etc.), which was necessary in order to recursively call a function. Presented below is a brief solution.
<!--- query for parent child tree --->
<cfquery name="tree_nodes" datasource="#sonis.ds#">
SELECT [location].[id],[location].[title], [location].[parent_id] FROM [location]
LEFT JOIN [location_category] ON [location].[id] = [location_category].[location_id]
WHERE [location_category].[category] = 'staff'
</cfquery>
<!--- build tree from adjacency list function --->
<cffunction name="build_tree" access="public" output="true">
<cfargument var name="tree_nodes" type="query" required="true"/>
<cfargument var name="parent_id" type="numeric" required="false" default="0"/>
<cfargument var name="depth" type="numeric" required="false" default="0"/>
<cfset var local = {}/>
<cfquery name="local.child_node" dbtype="query">
SELECT id, parent_id, title
FROM arguments.tree_nodes
WHERE parent_id = <cfqueryparam value="#arguments.parent_id#" cfsqltype="cf_sql_integer" />
ORDER BY id ASC
</cfquery>
<cfset var branch = {}/>
<cfset var counter = 1/>
<cfloop query="local.child_node">
<cfset local.depth = arguments.depth/>
<cfset branch[counter++] = {
'id' = '#local.child_node.id#',
'title' = '#local.child_node.title#',
'parent_id' = '#local.child_node.parent_id#',
'depth' = local.depth,
'children' = build_tree(arguments.tree_nodes, local.child_node.id,++local.depth)
} />
</cfloop>
<cfreturn branch/>
</cffunction>
<!--- print tree as select box function --->
<cffunction name="print_tree_select" access="public" output="true">
<cfargument var name="tree" type="struct" required="true"/>
<cfargument var name="selected" type="numeric" required="false" default="0"/>
<cfargument var name="child" type="numeric" required="false" default="0"/>
<cfif child eq '0'><select name="select_tree"><option value="null"></option></cfif>
<cfloop from="1" to="#StructCount(arguments.tree)#" index="a">
<option value="#arguments.tree[a]['id']#"<cfif #arguments.selected# eq #arguments.tree[a]['id']#> selected</cfif>>
<cfif #arguments.tree[a]['depth']# GT 0>
#RepeatString('--', arguments.tree[a]['depth'])#
</cfif>
#arguments.tree[a]['title']#
</option>
<cfif StructKeyExists(arguments.tree[a], 'children') AND StructCount(arguments.tree[a]['children']) GT 0>
#print_tree_select(arguments.tree[a]['children'],arguments.selected, 1)#
</cfif>
</cfloop>
<cfif child eq '0'></select></cfif>
</cffunction>
<!--- print tree as list function --->
<cffunction name="print_tree_list" access="public" output="true">
<cfargument var name="tree" type="struct" required="true"/>
<ul style="list-style-type: circle;">
<cfloop from="1" to="#StructCount(arguments.tree)#" index="local.i">
<li>
<cfform method="post" name="edit">
#arguments.tree[local.i]['title']#
<cfinput type="hidden" name="id" value="#arguments.tree[local.i]['id']#"/>
<cfinput type="Submit" name="command" value="Edit"/>
</cfform>
<cfif StructKeyExists(arguments.tree[local.i], 'children') AND StructCount(arguments.tree[local.i]['children']) GT 0>
#print_tree_list(arguments.tree[local.i]['children'])#
</cfif>
</li>
</cfloop>
</ul>
</cffunction>

Replace data in CFC

I have a simple CFC page which output data in a JSON format:
<cffunction name="test" access="remote" returnformat="plain" output="true">
<cfquery datasource="#dns#" name="rs.q" maxrows="5">
select text
from table
</cfquery>
<cfreturn serializeJSON( rs.q ) />
</cffunction>
The text outputted by the query can contain images, e.g., /webimages/1.jpg. Now for the webservice I want to search for images and replace them with http://domain.com/webimages/1.jpg.
Can that be done in the CFC file?
<cffunction name="test" access="remote" returnformat="json" output="false">
<cfquery datasource="#dns#" name="local.rs.q" maxrows="5">
select replace(text, "/webimages/", "http://domain.com/webimages/") as text
from table
</cfquery>
<cfreturn rs.q>
</cffunction>
or
<cffunction name="test" access="remote" returnformat="plain" output="false">
<cfquery datasource="#dns#" name="local.rs.q" maxrows="5">
select text
from table
</cfquery>
<cfreturn replace(serializeJSON(rs.q),
"\/webimages\/",
"http:\/\/domain.com\/webimages\/",
"all")>
</cffunction>

how to get Exception details from CFC file

I have a Function in CFC file, which will be called from .cfm file like below
<cffunction name="cftest" access="public" returntype="query" output="true" hint="Function returns Records">
<cfquery name="qryTest" datasource="DBTest">
select * from emp_tab;
</cfquery>
<cfreturn selectRecordsResultSet />
</cffunction>
How can I handle DB Exception using cftry? as this is returning Query, Is it possible to catch the DB Exception and pass the Details to the other page from where it is called?
Thanks
Here is an example of my usual implementation of this:
<cffunction name="getCurrentRecordsCount" access="public" output="false" returntype="any" hint="Get total history records count">
<cfargument name="filters" type="struct" required="false" default="#StructNew()#" hint="Filtering rules">
<cfset var qGetRecordCount = "" />
<cftry>
<cfquery datasource="#variables.dsn#" name="qGetRecordCount">
SELECT COUNT(*) AS cnt FROM ....
</cfquery>
<cfreturn qGetRecordCount.cnt />
<cfcatch type="any">
<cfreturn error(cfcatch.message, cfcatch.detail) />
</cfcatch>
</cftry>
</cffunction>
If you want to handle only database errors, change type to the database.
Errors handling and reporting performed using these three methods:
<cffunction name="error" access="private" output="false" returntype="boolean" hint="Set error status and message">
<cfargument name="message" type="string" required="true" hint="Error message text" />
<cfargument name="detail" type="string" required="false" default="" hint="Error detail text" />
<cfset variables.fError = true />
<cfset variables.fErrorText = arguments.message />
<cfif Len(arguments.detail)>
<cfset variables.fErrorText = variables.fErrorText & " [" & arguments.detail & "]" />
</cfif>
<cfreturn false />
</cffunction>
<cffunction name="gotError" access="public" output="false" returntype="boolean" hint="Return latest error flag state">
<cfreturn variables.fError />
</cffunction>
<cffunction name="getError" access="public" output="false" returntype="string" hint="Return latest error text and reset the flag">
<cfset var txt = variables.fErrorText />
<cfset variables.fError = false />
<cfset variables.fErrorText = "" />
<cfreturn txt />
</cffunction>
Please note that for methods with returntype="void" I use cfset instead of cfreturn:
<cfset error(cfcatch.message, cfcatch.detail) />
So in code I can do the following (cfscript):
// calculate filtered records count
totalLogCount = request.loggingService.getCurrentRecordsCount(filters);
// check if error was thrown
if (request.loggingService.gotError()) {
// report the error details somehow
WriteOutput(request.loggingService.getError());
}