Difference between #5 and #4 of Display an AJAX tree from your DB using CTreeView

unchanged
Title
Display an AJAX tree from your DB using CTreeView
unchanged
Category
Tutorials
changed
Tags
AJAX
unchanged
Content
This example uses a MySQL DB with a table named `tree` with the fields `id`,
`name`, and `parent_id`.

~~~~
[sql]
CREATE TABLE tree (
  id INTEGER UNSIGNED,
  name VARCHAR(50) NOT NULL,
  parent_id INTEGER UNSIGNED,
  PRIMARY(id)
)
~~~~

In your view, add:

~~~~
[php]
<?php
$this->widget(
	'CTreeView',
	array('url' => array('ajaxFillTree'))
);
?>
~~~~

This will create a tree widget on your page, and its data will be fetch using
the `ajaxFillTree` of the current controller.

So we have to add this action to the controller:

~~~~
[php] 
	/**
	 * Fills the JS tree on an AJAX request.
	 * Should receive parent node ID in $_GET['root'],
	 *  with 'source' when there is no parent.
	 */
	public function actionAjaxFillTree()
	{
		if (!Yii::app()->request->isAjaxRequest) {
			exit();
		}
		$parentId = 0;
		if (isset($_GET['root'])) {
			$parentId = (int) $_GET['root'];
		}
		$req = Yii::app()->db->createCommand(
			"SELECT m1.id, m1.name AS text, m2.id IS NOT NULL AS hasChildren "
			. "FROM tree AS m1 LEFT JOIN tree AS m2 ON m1.id=m2.parent_id "
			. "WHERE m1.parent_id <=> $parentId "
			. "GROUP BY m1.id ORDER BY m1.name ASC"
		);
		$children = $req->queryAll();
		echo str_replace(
			'"hasChildren":"0"',
			'"hasChildren":false',
			CTreeView::saveDataAsJson($children)
		);
		exit();
	}
~~~~

When the page loads, an AJAX request will be sent to fill the first level of the
tree. It'll have the GET parameter `root` to `source`. We suppose here that
the corresponding nodes have a `parent_id` of 0. You can replace this by `NULL`
if necessary, and the SQL request will still work because it uses `<=>`
instead of `=`).

Then we read the data in the database. We need a LEFT JOIN to find if a node has
children. If each row already has a `hasChildren` field, you can remove this
join and your SQL will be faster.

When sending the JSON-encoded result, there's a little trick: the
javascript wants the `hasChildren` attribute to be a boolean. But the SQL result
just contains 0 or 1, so we have to convert it, at least for the
"false" case. Instead of operating on the string result, one could
modify the PHP array with a `foreach`.

The `exit()` might not be necessary, but if you enabled the logs to Firebug,
then Yii will write some JS at the end of your response, and it will break your
AJAX.

### Links
[Chinese version](http://projects.ourplanet.tk/node/100)