CakePHPでTreeBehaviorで作ったカテゴリをわかりやすく一覧表示する


TreeBehaviorを利用して作成したカテゴリーを、それ用のビヘイビアとヘルパーを自作して以下のように視覚的にわかりやすく表示する。

![Screen Shot 0026-11-01 at 午後4.44.24.png](https://qiita-image-store.s3.amazonaws.com/1034/18614/e0f6f528-3e20-efae-75b2-a9c471a937ad.png)


# 準備

## まずGroupTreeビヘイビアを作成

```php:app/Model/Behavior/GroupTree.php
<?php
class GroupTreeBehavior extends TreeBehavior {
    function generatetreegrouped(&$Model, $conditions = null, $keyPath = null, $valuePath = null, $groupPath = null, $recursive = null) {
        $overrideRecursive = $recursive;
        extract($this->settings[$Model->alias]);
        if (!is_null($overrideRecursive)) {
            $recursive = $overrideRecursive;
        }

        if ($keyPath == null && $valuePath == null && $groupPath == null && $Model->hasField($Model->displayField)) {
            $fields = array($Model->primaryKey, $Model->displayField, 'parent_id', $left, $right);
        } else {
            $fields = null;
        }

        if ($keyPath == null) {
            $keyPath = '{n}.' . $Model->alias . '.' . $Model->primaryKey;
        }

        if ($valuePath == null) {
            $valuePath = '{n}.' . $Model->alias . '.' . $Model->displayField;
        }
        
        if ($groupPath == null) {
            $groupPath = '{n}.' . $Model->alias . '.parent_id';
        }
        
        $order = $Model->alias . '.' . $left . ' asc';
        $results = $Model->find('all', compact('conditions', 'fields', 'order', 'recursive'));
        $stack = array();

        foreach ($results as $i => $result) {
            while ($stack && ($stack[count($stack) - 1] < $result[$Model->alias][$right])) {
                array_pop($stack);
            }
            $stack[] = $result[$Model->alias][$right];
        }
        if (empty($results)) {
            return array();
        }
        return Set::combine($results, $keyPath, $valuePath, $groupPath);
    }
}
?>

```

## Treeヘルパーも作成

```php:app/View/Helper/TreeHelper.php
<?php
App::uses('AppHelper', 'View/Helper');

class TreeHelper extends AppHelper {
    
    function getCategories($key, $categories, &$mainList) {
        
        //一番最初のul
        if($key == 0){
            $result = '<ul id="browser" class="filetree">';     
        } else {
            $result = '<ul>';     
        }
        
        foreach($categories as $catKey => $name) {
            $result .= $this->getCategory($catKey, $name, $mainList);
        }
        $result .= '</ul>';
        return $result;
    }
    
    function getCategory($key, $value, &$mainList) {
        $result = '<li class="closed">';
        
        if(array_key_exists($key, $mainList)) {
            //子カテゴリを持つカテゴリ
            $result .= '<span class="folder">'.$value.'</span>';
        } else {
            //子無しカテゴリ
            $result .='<span class="file">'. $value.'</span>';
        }
    
        
        if(array_key_exists($key, $mainList)) {
            $result .= $this->getCategories($key, $mainList[$key], $mainList);
        }
        $result .= '</li>';
        return $result;
    }    
}
```


# 使い方


## Modelでビヘイビアを読み込む

```php:app/Model/Category.php
	public $actsAs = array('Tree', 'GroupTree');
```


## Controllerで作ったヘルパーを読み込み、アクションを用意する

```php:app/Controller/CategoriesController.php
	public $helpers = array('Tree');

	public function index() {
		$categories = $this->Category->generatetreegrouped();
        $this->set(compact('categories'));
	}
```

## View

```php:app/View/Categories/index.ctp
<?    
	if(array_key_exists(0, $categories)) {
		echo $this->Tree->getCategories(0, $categories[0], $categories);
	}
?>
```

以上。