Ask Ben: Simple Recursion Example

<cffunction
	name="OutputChildren"
	access="public"
	returntype="void"
	output="true"
	hint="Outputs the children of a given parent.">
 
	<!--- Define arguments. --->
	<cfargument
		name="Data"
		type="query"
		required="true"
		hint="Family tree data query."
		/>
 
	<cfargument
		name="ParentID"
		type="numeric"
		required="false"
		default="0"
		hint="The ID of the parent who's children we want to output."
		/>
 
	<!--- Define the local scope. --->
	<cfset var LOCAL = StructNew() />
 
 
	<!--- Query for the children of the given parent. --->
	<cfquery name="LOCAL.Children" dbtype="query">
		SELECT
			id,
			name
		FROM
			ARGUMENTS.Data
		WHERE
			parent_id = <cfqueryparam value="#ARGUMENTS.ParentID#" cfsqltype="cf_sql_integer" />
		ORDER BY
			name ASC
	</cfquery>
 
 
	<!---
		Check to see if we found any children. This is our
		END case scenario. If there are no children then our
		recursion will come to a stop for this path.
	--->
	<cfif LOCAL.Children.RecordCount>
 
		<ul>
			<!--- Loop over children. --->
			<cfloop query="LOCAL.Children">
 
				<li>
					#LOCAL.Children.name#
 
					<!---
						Now that we are looking at a particular
						child, we want to recursively call this
						function (from within itself) to see if
						this child has, itself, some children.
 
						We are passing along the same data set,
						but instead of passing along the
						original ParentID, we passing along THIS
						child's ID as the next round or Parent
						IDs.
					--->
					<cfset OutputChildren(
						Data = ARGUMENTS.Data,
						ParentID = LOCAL.Children.id
						) />
				</li>
 
			</cfloop>
		</ul>
 
	</cfif>
 
	<!--- Return out. --->
	<cfreturn />
</cffunction>

For Cut-and-Paste