Difference between #3 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
unchanged
Tags
changed
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)version](http://dreamneverfall.cn/node/100)