You put the recursive call to "traverse" in the wrong place - it should be
within the traverse function itself instead of in init. Traverse should
read like this:
<cffunction name="traverse" access="public" output="true" returntype="any">
<cfargument name="nodeid" type="numeric" required="yes" />
<cfset var _recordset = "" />
<cfset var _collectiondao =
createobject('component','messagegateway') />
<cfset var i = 0 />
<cfset var _child = createobject('component', 'nodebean') />
<cfset _recordset = _collectiondao.selectmessagebyparent(
arguments.nodeid ) />
<cfif _recordset.recordcount>
<cfscript>
for(i = 1; i lte _recordset.recordcount; i = i+1){
writeoutput(_recordset.messageid[i] & '<br />');
_child = createobject('component', 'nodebean').init(
_recordset.messageid[i], arguments.nodeid );
addchild( _child );
TRAVERSE(_CHILD.NODEID);
}
</cfscript>
<cfelse>
<cfreturn />
</cfif>
</cffunction>
The problem with your current method is that you keep creating new
instances, which means you never have the shared array "instance.children".
Some other minor modifications may also need to be done.
Hope this points you in the right direction,
Roland
-----Original Message-----
From: [EMAIL PROTECTED] [mailto:[EMAIL PROTECTED] On Behalf
Of Allan Casabar
Sent: Thursday, April 01, 2004 3:59 AM
To: [EMAIL PROTECTED]
Subject: [CFCDev] Recursion in CFC
Hello,
I am trying to make a threaded discussion board using CFC. However
something about recursion in CF / CFC stumped me. It seems that i can't
make a function return to it's calling function. The result of this
behaviour is that i will only be able to add the first child of the node
unless in cases where that current node don't have any children. Sorry
if i don't make sense. However i copy pasted the source codes and the
content of the database, expected output, and actual output involved in
this problem. Any help regarding this problem is greately appreciated.
This is the current contents of the DB / message table
messageid parentid
1 0
2 1
3 1
4 2
5 4
6 4
My output if I invoke generatetree method on treefactory.cfc is
1
2
4
5
6
My expected output is
1
2
4
5
6
3
As you can see it only traverse the tree in one direction since it fails
to return to the calling function and output 3.
Also please bear with my codes since this is just for rapid prototyping
of the application..
<!--- nodebean.cfc --->
<!--- kind of an abstract product for messages --->
<!--- nodeid is the same as messageid for message object --->
<cfcomponent displayname="nodebean">
<cfscript>
variables.instance.nodeid = 0;
variables.instance.parentid = 0;
variables.instance.children = arraynew( 1 );
</cfscript>
<cffunction name="init" access="public" output="false"
returntype="struct">
<cfargument name="nodeid" type="numeric" required="yes" />
<cfargument name="parentid" type="numeric" required="yes" />
<cfset setnodeid( arguments.nodeid ) />
<cfset setparentid( arguments.parentid ) />
<cfset traverse( arguments.nodeid ) />
<cfreturn this />
</cffunction>
<!--- getters and setters --->
<cffunction name="setnodeid" access="public" output="false"
returntype="void">
<cfargument name="nodeid" type="numeric" required="true">
<cfset variables.instance.nodeid= arguments.nodeid/>
</cffunction>
<cffunction name="getnodeid" access="public" output="false"
returntype="numeric">
<cfreturn variables.instance.nodeid/>
</cffunction>
<cffunction name="setparentid" access="public" output="false"
returntype="void">
<cfargument name="parentid" type="numeric" required="true">
<cfset variables.instance.parentid= arguments.parentid/>
</cffunction>
<cffunction name="getparentid" access="public" output="false"
returntype="numeric">
<cfreturn variables.instance.parentid/>
</cffunction>
<cffunction name="addchild" access="public" output="false"
returntype="void">
<cfargument name="node" type="struct" required="yes" />
<cfset arrayappend(variables.instance.children, node) />
</cffunction>
<cffunction name="getchildren" access="public" output="false"
returntype="array">
<cfreturn variables.instance.children />
</cffunction>
<cffunction name="traverse" access="public" output="true"
returntype="any">
<cfargument name="nodeid" type="numeric" required="yes" />
<cfset var _recordset = "" />
<cfset var _collectiondao = createobject('component',
'messagegateway') />
<cfset var i = 0 />
<cfset var _child = createobject('component', 'nodebean') />
<cfset _recordset = _collectiondao.selectmessagebyparent(
arguments.nodeid ) />
<cfif _recordset.recordcount>
<cfscript>
for(i = 1; i lte _recordset.recordcount; i = i+1){
writeoutput(_recordset.messageid[i] & '<br />');
_child = createobject('component', 'nodebean').init(
_recordset.messageid[i], arguments.nodeid );
addchild( _child );
}
</cfscript>
<cfelse>
<cfreturn />
</cfif>
</cffunction>
</cfcomponent>
<!--- tree factory --->
<!-- will take a nodeid as an argument and generate the tree / subtree
for that node --->
<cfcomponent displayname="treefactory">
<cffunction name="generatetree" access="public" output="true"
returntype="any">
<cfargument name="nodeid" type="numeric" required="yes" />
<cfset var _cruddao = createobject('component', 'messagedao') />
<cfset var _collectiondao = createobject('component',
'messagegateway') />
<cfset var _recordset = "" />
<cfset var _node = createobject('component', 'nodebean') />
<cfset var _child = createobject('component', 'nodebean') />
<cfset var i = 0 />
<cfset _recordset = _cruddao.selectmessage( arguments.nodeid ) />
<cfif _recordset.recordcount>
<cfscript>
_node = createobject('component', 'nodebean').init(
_recordset.messageid, _recordset.parentid );
</cfscript>
</cfif>
<cfreturn _node />
</cffunction>
</cfcomponent>
<!--- message gateway--->
<!--- data abstraction layer for queries that will return a collection
(multiple records) --->
<cfcomponent displayname="messagegateway">
<cffunction name="selectforumthreads" access="public" output="false"
returntype="query">
<cfargument name="forumid" type="numeric" required="no"
default="0" />
<cfset var qryselectforumthreads = "" />
<cfquery name="qryselectforumthreads" datasource="#request.dsn#"
username="#request.username#" password="#request.password#">
SELECT
*
FROM
message
WHERE
forumid = <cfqueryparam value="#arguments.forumid#"
cfsqltype="cf_sql_integer" />
AND threadid = <cfqueryparam value="0"
cfsqltype="cf_sql_integer" />
</cfquery>
<cfreturn qryselectforumthreads />
</cffunction>
<cffunction name="selectmessagebyparent" access="public"
output="false" returntype="query">
<cfargument name="parentid" type="numeric" required="yes" />
<cfset var qryselectmessagebyparent = "" />
<cfquery name="qryselectmessagebyparent"
datasource="#request.dsn#" username="#request.username#"
password="#request.password#">
SELECT
messageid
FROM
message
WHERE
parentid = <cfqueryparam value="#arguments.parentid#"
cfsqltype="cf_sql_integer" />
</cfquery>
<cfreturn qryselectmessagebyparent />
</cffunction>
</cfcomponent>
----------------------------------------------------------
You are subscribed to cfcdev. To unsubscribe, send an email
to [EMAIL PROTECTED] with the words 'unsubscribe cfcdev'
in the message of the email.
CFCDev is run by CFCZone (www.cfczone.org) and supported
by Mindtool, Corporation (www.mindtool.com).
An archive of the CFCDev list is available at
www.mail-archive.com/[EMAIL PROTECTED]
----------------------------------------------------------
You are subscribed to cfcdev. To unsubscribe, send an email
to [EMAIL PROTECTED] with the words 'unsubscribe cfcdev'
in the message of the email.
CFCDev is run by CFCZone (www.cfczone.org) and supported
by Mindtool, Corporation (www.mindtool.com).
An archive of the CFCDev list is available at www.mail-archive.com/[EMAIL PROTECTED]