> THis is my first program ever outside of school, and I learned about OOP with
> JAVA in school, but never really got to apply it, I know there is some rule I
> am breaking or something for CFC's and maybe even the OOP concept all
> together...
Right. First things first then: you might need to brush up a bit on what
you're trying to achieve. Given yourself a refreshed in OO concepts.
Here's one link:
http://en.wikipedia.org/wiki/Object-oriented_programming
And Google will have plenty more, if the Wikipedia article is a bit dry (be
warned: almost all coverage of OO concepts will be a bit dry!)
Next, read the docs on CFCs that Adobe very kindly expose to the public,
here:
http://livedocs.adobe.com/coldfusion/8/htmldocs/help.html?content=buildingCompon
ents_01.html
Specifically, read and understand the coverage of the different variables
scopes available to CFC instances, and how to use them:
http://livedocs.adobe.com/coldfusion/8/htmldocs/help.html?content=buildingCompon
ents_01.html
> <cffunction name="noShowFilterList" returntype="any" access="remote">
> <cfset filterList = "69.15.59.174">
You should be VARing this variable. And all variables local to a method.
If it IS actually your intent for the variable to be global to the CFC
instance, SCOPE IT as variables.filterList. CF will work out what you mean
without the scoping, but you can make the life easier of humans reading the
code if you scope your variables as much as possible, whether they "need"
it or not.
> <cfoutput query="getFilterIPInfo">
Where did this query come from? You didn't pass it in to the method. Is
it an argument? (You should have a <cfargument> tag for it, and you should
scope it. Is it a instance-wide variables (variables scope)? Scope it for
clarity. Similarly if it is THIS-scoped.
> <cfset filterList = filterList & "," & getFilterIPInfo.ipAddress>
> </cfoutput>
You don't need to have this loop. Just use valueList().
> <cffunction name="getFilteredLinkDetail" access="remote" returntype="any">
> <cfparam name="PageNum_queryDetails" default="1">
I suspect this should be a VAR statement.
> <cfquery name="queryDetails" datasource="clickTrackSystem">
This should be VARed.
> SELECT *
Using SELECT * is generally poor practice. Do you actually WANT every
column from the query, irrespective of what those columns are? I suspect
not. SELECT only the columns you intend to use; it's much less work for
the DB server and the CF server.
> WHERE linkID = #url.l# AND NOT (FIND_IN_SET(Clicks.ipAddy, "#filterList#"))
In referring to a URL-scoped variable directly in your CFC code, you are
limiting the reusability of the CFC. This value should be passed in.
And you should NEVER EVER use a URL-scope variable directly in a query
anyhow. Google "SQL injection".
Always use <cfqueryparam> tags in your queries, when using dynamic values.
Otherwise all your SQL will be treated as dynamic SQL by the DB server, and
you'll end up with 100s of individually compiled and never-reused queries
sitting on your DB server. Initial compilation has quite an overhead which
you'll want to minimise. Parameterising queries also prevents the chance
of SQL injection.
> <cfset newFilter=CreateObject('component', 'Filter')>
> <!--- Query all Filtered IPs --->
> <cfinvoke component="#newFilter#" method="displayFilteredIPs"
> returnvariable="getFilterIPInfo">
Right. So this is where that query comes from. However...
> <cfinvoke component="#newFilter#" method="noShowFilterList"
> returnvariable="filterList">
... you're never passing it in to the method call, are you? So how's the
method supposed to know about it? Code in CFCs know ONLY about their own
VARIABLES scope; they have no idea about the calling-code's VARIABLES
scope. You need to pass in calling-code variables that you wish the CFC
method to have access to.
> <cfinvoke component="#newLink#" method="displayLinks"
> returnvariable="getLinkInfo">
Can I recommend that instead of using all these clunky <cfinvoke> tags, you
simply:
<cfset getLinkInfo = newLink.displayLinks()>
It's much cleaner.
<cfinvoke> is a bit of a lemon of a tag, for most of its "recommended" (in
the docs, that is) uses.
> Variable filterList is undefined.
> The error occurred in /Links.cfc: line 57
>
> 55 : SELECT Clicks.linkID
> 56 : FROM Clicks
> 57 : WHERE Clicks.linkID = #getLinkInfo.linkID# AND NOT
I hope you understand why this is, now?

Signature
Adam
TomD - 27 Aug 2007 19:35 GMT
"... you're never passing it in to the method call, are you? So how's the
method supposed to know about it? Code in CFCs know ONLY about their own
VARIABLES scope; they have no idea about the calling-code's VARIABLES
scope. You need to pass in calling-code variables that you wish the CFC
method to have access to."
I understand what you are saying, but I don't know how. I thought since the
cfm page had filterlist as a return variable then the page would pass that
variable to the cfc when the method was called. Obiviously I was wrong, I even
tried, knowing it was not right, to create and object of Filter and invoke that
method with the query in the Links cfc, and of course I was right it didn't
work. That was basically my question...how do I get Links.cfc to know what
filterlist is? Note I will take your better practices suggestions once I get
this all figured out, I put variables.filterList and it just threw and error
that filterList was undefined in variables, and that threw me off, so once I
get this going I will go back and fix it, but I am confused enough for now
Here is what I have tried:
[b] [i]a new fucntion in Links.cfc[/i][/b]
[b]<cffunction name="passFilterList">
<cfargument name="filterList" required="no" type="string">
<cfset this.filterList = arguments.filterList>
</cffunction>[/b]
[b][i] the query in the function that does the output[/i][/b]
[b]...
<cfquery name="countHits" datasource="clickTrackSystem">
SELECT Clicks.linkID
FROM Clicks
WHERE Clicks.linkID = #getLinkInfo.linkID# AND NOT
(FIND_IN_SET(Clicks.ipAddy, "#filterList#"))
</cfquery>
...
[/b]
[b] new code for campaign.cfm [/b]
[b]<!--- Create a Filter Object --->
<cfset newFilter=CreateObject('component', 'Filter')>
<!--- Query all Filtered IPs --->
<cfinvoke component="#newFilter#" method="displayFilteredIPs"
returnvariable="getFilterIPInfo">
<cfinvoke component="#newFilter#" method="noShowFilterList"
returnvariable="filterList">
<cfdump var = "#filterList#"> <!--- Its there! --->
<!--- Create an Object of type Links from Links.cfc--->
<cfset newLink = CreateObject('component', 'Links')>
<!--- Query the link info--->
<cfset newLink.passFilterList('#filterList#')>
<cfinvoke component="#newLink#" method="displayLinks"
returnvariable="getLinkInfo">
.....
[i]I even pass it down here[/i]
<!--- Display Link information--->
<cfset newLink.linkInfo('#filterList#')>
[/b]
Still filterList is undefined, I even tried putting filterList into another
variable and passing it using the new variable, but no, no no I can't get
Links.cfc to comply
btw I need cfinvoke when my functions have queries in them....right?
"> <cffunction name="getFilteredLinkDetail" access="remote" returntype="any">
> <cfparam name="PageNum_queryDetails" default="1">
I suspect this should be a VAR statement."
funny you mention that because I get an error for that as well, I use it in
the table in the page, and it is undefined, I changed it like this:
<cfset VAR PageNum_queryDetails = "1">
and still undefined, is that not what you meant?
"> <cfquery name="queryDetails" datasource="clickTrackSystem">
This should be VARed.
"
How do you VAR a query?
"> <cfset filterList = filterList & "," & getFilterIPInfo.ipAddress>
> </cfoutput>
You don't need to have this loop. Just use valueList().
"
I found syntax for this and I understand it, but how can I tell it to start
out with a value and add the list to that value the way we have it set up now?
We need to put our IP address in the list first and then tack on what it finds
in the database, if we put it in the Database, we will have to put it in there
for every client.
Thanks in advance for you patience and help
Adam Cameron - 27 Aug 2007 21:09 GMT
> I understand what you are saying, but I don't know how.
Right.
Did you read all that bumpf I gave you the link for, before (about CFCs)?
That was an awful lot of it to:
a) read over;
b) investigate and experiment with.
I didn't mean just the single pages I referenced, I meant the ensuing
section (there's about 30-odd pages in it). There are next/prev arrows @
the top right of each page.
I recommend you ditch your immediate requirement, and work on the examples
given in the docs for a bit until you get your head around them. And then
return to your specific problem once you've done that.
> cfm page had filterlist as a return variable then the page would pass that
> variable to the cfc when the method was called.
Only if you tell it to. You need to pass in these values into CFC methods
just like you would any other function.
You'd not have code like this:
<cfset stringToTrim = "Hello World">
<cfset charactersWanted = 5>
<cfset newString = left()>
And expect newString to contain "Hello". No, you need to pass the values
to the function:
<cfset newString = left(stringToTrim, charactersWanted)>
CFC methods are the same. They're just functions. For them to receive a
value, you have to pass them in.
This IS all covered in the docs I pointed you to.
> Note I will take your better practices suggestions once I get
> this all figured out,
Makes sense. Like I suggested: I'd back off even further and try the more
simple examples in the docs first.
> funny you mention that because I get an error for that as well, I use it in
> the table in the page, and it is undefined, I changed it like this:
> <cfset VAR PageNum_queryDetails = "1">
> and still undefined, is that not what you meant?
Just as a practice, one should always VAR variables used in functions. I
was not meaning to suggest it'd fix your issue, just something you should
be doing.
>>> <cfquery name="queryDetails" datasource="clickTrackSystem">
>> This should be VARed.
> How do you VAR a query?
A query is just a variable, like any other variable. So one vars it in the
same way.
<cfset var queryDetails = ""><!--- any old value is fine --->
...
<cfquery name="queryDetails" datasource="clickTrackSystem">
>>> <cfset filterList = filterList & "," & getFilterIPInfo.ipAddress>
>> You don't need to have this loop. Just use valueList().
> I found syntax for this and I understand it, but how can I tell it to start
> out with a value and add the list to that value the way we have it set up now?
Right. You have a string (filterList) and you want to preprend it to a
list (the result of your valueList() call).
You could either treat your valueList() as a string and prepend filterList
in exactly the same way as you are above (just without the loop), or you
could approach it from the "list" perspective and investigate which list
functions might help you there.
http://livedocs.adobe.com/coldfusion/8/htmldocs/functions-pt0_13.html#1099435
> Thanks in advance for you patience and help
No prob. Sorry to not just be answering your questions directly (ie: "the
answer to your problem is [this]"), but I don't believe that approach is
very helpful, in the long run. I think it's best to learn what the answer
is, rather than to be told it.

Signature
Adam
TomD - 27 Aug 2007 21:37 GMT
you are absolutely right, I will be studying on this for the rest of the day and more tomorrow, and post sometime tomorrow afternoon
Thanks
TomD - 31 Aug 2007 18:59 GMT
I got it ironed out using the variables scope, I still need to wrap my head around some stuff but I am just glad it works, thanks for the help!
Adam Cameron - 27 Aug 2007 20:52 GMT
> Specifically, read and understand the coverage of the different variables
> scopes available to CFC instances, and how to use them:
> http://livedocs.adobe.com/coldfusion/8/htmldocs/help.html?content=buildingCompon
ents_01.html
Sorry, that should read
http://livedocs.adobe.com/coldfusion/8/htmldocs/buildingComponents_29.html.

Signature
Adam
Thank you Adam, I will get to work on this right now, and let you know how it
goes...
"> <cfoutput query="getFilterIPInfo">
Where did this query come from? You didn't pass it in to the method. Is
it an argument? (You should have a <cfargument> tag for it, and you should
scope it. Is it a instance-wide variables (variables scope)? Scope it for
clarity. Similarly if it is THIS-scoped."
The query getFilterInfo, is in another method in the same CFC
'THIS' is something I just don't understand, I can never find any OO examples
where there is interaction with databases.
I will take a look at those websites you gave me and begin trying to work all
this out, you should be hearing more from me later on in the day...
Thanks