Display an AJAX tree from your DB using CTreeView

You are viewing revision #3 of this wiki article.
This version may not be up to date with the latest version.
You may want to view the differences to the latest version.

next (#4) »

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://dreamneverfall.cn/node/100)
19 0
21 followers
Viewed: 73 391 times
Version: Unknown (update)
Category: Tutorials
Written by: François Gannaz
Last updated by: François Gannaz
Created on: Apr 7, 2010
Last updated: 12 years ago
Update Article

Revisions

View all history

Related Articles