unchanged
Title
Display an AJAX tree from your DB using CTreeView
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)