Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

build Tree trong sifoni #7

Open
evansnguyen0104 opened this issue Sep 23, 2015 · 0 comments
Open

build Tree trong sifoni #7

evansnguyen0104 opened this issue Sep 23, 2015 · 0 comments

Comments

@evansnguyen0104
Copy link

1.Vấn Đề

Chúng ta có một mảng như sau :

Array
(
    [1] => Array
        (
            [id] => 1
            [name] => Tin Tức
            [parent_id] => 0
        )

    [2] => Array
        (
            [id] => 2
            [name] => Công Nghệ
            [parent_id] => 0
        )

    [3] => Array
        (
            [id] => 3
            [name] => Tin Trong Nước
            [parent_id] => 1
        )

    [4] => Array
        (
            [id] => 4
            [name] => Tin Nước Ngoài
            [parent_id] => 1
        )

    [5] => Array
        (
            [id] => 5
            [name] => Điện Thoại
            [parent_id] => 2
        )

    [6] => Array
        (
            [id] => 6
            [name] => Laptop
            [parent_id] => 2

Mảng này rất hay gặp khi chúng ta truy vấn dữ liệu từ bảng category ra để load dữ liệu lên menu.Với menu cấp 1 chính là những thành phần có parent_id = 0 và menu con của nó là những thành phần có parent_id = id danh mục chính.
Giờ ta làm gọn lại mảng này để có dạng như sau :

Array
(
     1 => Array
        (
            [id] => 1
            [parent_id] => 0
            [name] => Tin Tức
            [children] => Array
                (
                    3=> Array
                        (
                            [id] => 3
                            [name] => Tin Trong Nước
                            [parent_id] => 1
                     4 => Array
                        (
                            [id] => 4
                            [name] => Tin Trong Quốc Tế
                            [parent_id] => 1
                        )
                )
    2 => Array
        (
            [id] => 2
            [name] => Công Nghệ
            [parent_id] => 0
            [children] => Array
                (
                    5 => Array
                        (
                            [id] => 5
                            [name] => Điện Thoại
                            [parent_id] => 2
                        )
                )
                                (
                    6 => Array
                        (
                            [id] => 6
                            [name] => Laptop
                            [parent_id] => 2
                        )
                )
        )

2.Phương Pháp

Sử dụng build Tree (thực tế là kỹ thuật lập trình đệ quy).Các bạn có thể tìm hiểu thêm về kỹ thuật lập trình đệ quy để hiểu hơn về phương pháp này.

3.Tiến Hành

Ở đây mình lấy 1 ví dụ mà hầu như mọi người hay sử dụng đó là load menu cho website
B1. Xây dựng hàm buildTree
Mở file hook.php trong thư mục config thêm đoạn code có nội dung như sau :

function buildTree(array $elements, $parentId = 0, $parent_id_field = 'parent_id') {
    $branch = array();

    foreach ($elements as $element) {
        if ($element[$parent_id_field] == $parentId) {
            $children = buildTree($elements, $element['id']);
            $element['children'] = empty($children) ? [] : $children;
            $branch[] = $element;
        }
    }

    return $branch;
}

Hàm này có 4 thông số truyền vào trong đó $elements chính là toàn bộ dữ liệu lấy ra ở bảng category dưới dạng mảng
B2. Sử dụng buildTree để gom dữ liệu trong model
Trong model category chúng ta tạo hàm 1 như sau :

  public function getTreeMenu() {
    $cats = Category::where('status','=','1')->get()->toArray();
    $tree = buildTree($cats);
    return $tree;
  }

B3. Controller lấy dữ liệu rồi đưa ra view
Trong Controller bạn lấy dữ liệu menu bằng $data['cats'] = Category::getTreeMenu(); Ở đây
mình sử dụng 1 file BlockController riêng để xử lý dữ liệu riêng cho những phần layout cố đinh.

<?php
namespace App\Controller;

use Sifoni\Controller\Base;
use App\Model\Post;
use App\Model\Category;

class BlockController extends Base
{
    public function renderMainMenuAction() {
        $data['cats'] = Category::getTreeMenu();
        return $this->render('default/block/main_menu.html.twig', $data);
    }

Như vậy dữ liệu xuất ra tại main_menu.html.twig.Dưới đây là mã code mình dùng

<div class="container">
    <ul>
        {% for c in cats %}
        <li><a href="/threads/{{c.target}}">{{c.name}}</a>
            <ul>
                {% for cc in c['children'] %}
                <li><a href="/threads/{{cc.target}}">{{cc.name}}</a></li>
                {% endfor %}
            </ul>
        </li>
        {% endfor %}
    </ul>
</div>

Mục đích mình sử dụng file main_menu.html.twig để render dữ liệu cho menu là để làm nó tách biệt cũng như giảm tải dòng code.Còn nếu các bạn không muốn phức tạp thì có thể lấy dữ liệu menu bằng $data['cats'] = Category::getTreeMenu(); trong controller và đỗ dữ liệu ra view bình thường.Nếu bạn sử dụng cách này thì có thể dừng lại tại đây là không cần làm tiếp bước dưới.

B4. Tạo routing render menu

Ở file routing.php bạn thêm dòng sau

 '/_block/main_menu' => 'BlockController:renderMainMenu:block_main_menu', 

B5. Đưa vùng render riêng cho menu vào layout

Ở file phân vùng block cho layout bạn gọi tới routing render cho menu.VD :

{% endblock %}
{% block navmenu %}
    {{ render(url('block_main_menu')) }}
{% endblock %} 

Như vậy bạn đã có được một cách để đỗ dự liệu cho menu mới.

4.Mở Rộng

Các bạn có thể sử dụng phương pháp này để áp dụng với trường hợp load các bài post theo category
Chúc các bạn thành công !

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant