zoukankan      html  css  js  c++  java
  • CTreeView 使用

    Display an AJAX tree from your DB using CTreeView

    20 followers

    The database

    This example uses a MySQL DB with a table named tree with the fields id, name, and parent_id. The parent_id will be NULL for root elements. The SQL is kept simple (no autoinc, no FK, etc).

    CREATE TABLE tree (
      id INTEGER UNSIGNED NOT NULL,
      name VARCHAR(50) NOT NULL,
      parent_id INTEGER UNSIGNED,
      PRIMARY KEY (id)
    )

    MySQL has no recursive queries. In order to fetch tree nodes, you have to recursively send SQL queries for each node, asking for its children. The easiest way to do so is to send these queries with AJAX, so that the tree can be displayed even if the deep nodes haven't been fetched yet. If you're using Oracle or Postgresql, there are other solutions, though this will also work.

    The view

    In your view, add:

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

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

    The controller

    So we have to add this action to the controller:

    /**
         * 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()
        {
            // accept only AJAX request (comment this when debugging)
            if (!Yii::app()->request->isAjaxRequest) {
                exit();
            }
            // parse the user input
            $parentId = "NULL";
            if (isset($_GET['root']) && $_GET['root'] !== 'source') {
                $parentId = (int) $_GET['root'];
            }
            // read the data (this could be in a model)
            $children = 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"
            )->queryAll();
            echo str_replace(
                '"hasChildren":"0"',
                '"hasChildren":false',
                CTreeView::saveDataAsJson($children)
            );
        }

    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 set to source (this is the behavior of the Treeview JS plugin that CTreeView uses). We suppose here that the corresponding nodes (the root nodes) have a parent_id set to NULL. In SQL, "=" can't compare a value with NULL, so we have to use the <=> operator instead.

    The other AJAX requests will have an integer value (the parent node's id) in $_GET['root']. We typecast this to "int" for security.

    Then the code reads 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.

    If AJAX fails

    If your AJAX query fails, you should try to debug it in your browser. Firefox, Chrome and Opera have good developer toolbars that will show you the AJAX requests sent and what their answers were. You may find that some HTML is appended at the end of the expected JSON answer. I had this problem with Yii'JS logs and a toolbar extension. In this case, insert an exit(); at the end of the action. Or even better: Yii::logger->flush(); exit();.

    Final note

    This is meant as a simple introduction. There are many ways to enhance this:

    • Refactor the controller action by putting its 2 last lines into a model.
    • Increase the abstraction level, so that the code can be used on various models, as long as they share the same table structure.
    • If the tree content rarely changes, you may consider using a different structure, like nested sets. This will make most queries easier, e.g. fetching the path of a node.
  • 相关阅读:
    云server之间实时文件同步和文件备份的最简单高效的免费方案
    小程序 通过栈的方式把,上个返回过的页面数据传到当前页面
    mpvue 实例
    mpvue配合less
    java随笔5 完整路径的应用
    java随笔4 java中接参整形转字符串
    java随笔2 变量类定义
    java随笔1 常用快捷键 补全和补全提示等
    对象(针对对象)
    事务的2种简单实例
  • 原文地址:https://www.cnblogs.com/xiongsd/p/3060971.html
Copyright © 2011-2022 走看看