Bonjour,

J'ai suivi les tutos de grafikart et au lieu de faire comme lui pour les catégories, j'ai utilisé le treeBehavior actsAs afin de pouvoir gérer facilement les catégories et sous-catégories.

Voici les codes:

Dans le controller categories , ma fonction nav pour récupérer toutes les catégories

function nav(){
         $categories = $this->Category->find('all');
         return ($categories);
    }

Puis, dans mon layout par défault

<?php echo $this->element('nav'); ?>

Dans View->Elements->nav.ctp

<ul>
    <li><?php echo $this->Html->link('Accueil', array('controller' =>'posts', 'action' =>'index')); ?></li>
    <?php $cat = $this->requestAction(array('controller' =>'categories', 'action'=>'nav', 'admin'=>false)); ?>
    <li>
        <a href="<?php echo $this->Html->url(array('controller'=>'posts','action'=>'category')); ?>" class="nav">      
        <?php echo $this->Tree->generate($cat); ?>          
        </a>
        <?php debug($cat); ?>
    </li>
</ul>

Dans le controller posts , pour afficher tous les posts lier à une catégorie quand on clique sur cette dernière

function category($category){
        $cat = $this->Post->Category->find('first',array(
            'conditions' => array('slug' => $category)
        ));
        if(empty($cat))
            throw new NotFoundException('Aucune catégorie ne correspond à ce nom'); 
        $d'posts'] = $this->Paginate('Post',array('type'=>'post','online'=>1,'category_id' => $cat'Category']'id']));
        $d'title'] = 'Tous les articles "'.$cat'Category']'name'].'"';
        $this->set($d);
        $this->render('index'); 
    }

Dans le TreeHelper

<?php
/**
* Tree Helper.
*
* Used the generate nested representations of hierarchial data
*
* PHP versions 4 and 5
*
* Copyright (c) 2008, Andy Dawson
*
* Licensed under The MIT License
* Redistributions of files must retain the above copyright notice.
*
* @filesource
* @copyright Copyright (c) 2008, Andy Dawson
* @link www.ad7six.com
* @package cake-base
* @subpackage cake-base.app.views.helpers
* @since v 1.0
* @version $Revision: 1358 $
* @modifiedBy $LastChangedBy: skie $
* @lastModified $Date: 2009-10-15 05:49:11 -0500 (Thu, 15 Oct 2009) $
* @license http://www.opensource.org/licenses/mit-license.php The MIT License
*/
/**
* Tree helper
*
* Helper to generate tree representations of MPTT or recursively nested data
*/
class TreeHelper extends AppHelper {
/**
* name property
*
* @var string 'Tree'
* @access public
*/
public $name = 'Tree';
/**
* settings property
*
* @var array
* @access private
*/
private $__settings = array();
/**
* typeAttributes property
*
* @var array
* @access private
*/
private $__typeAttributes = array();
/**
* typeAttributesNext property
*
* @var array
* @access private
*/
private $__typeAttributesNext = array();
/**
* itemAttributes property
*
* @var array
* @access private
*/
private $__itemAttributes = array();
/**
* helpers variable
*
* @var array
* @access public
*/
public $helpers = array ('Html');
/**
* Tree generation method.
*
* Accepts the results of
* find('all', array('fields' => array('lft', 'rght', 'whatever'), 'order' => 'lft ASC'));
* children(); // if you have the tree behavior of course!
* or findAllThreaded(); and generates a tree structure of the data.
*
* Settings (2nd parameter):
* 'model' => name of the model (key) to look for in the data array. defaults to the first model for the current
* controller. If set to false 2d arrays will be allowed/expected.
* 'alias' => the array key to output for a simple ul (not used if element or callback is specified)
* 'type' => type of output defaults to ul
* 'itemType => type of item output default to li
* 'id' => id for top level 'type'
* 'class' => class for top level 'type'
* 'element' => path to an element to render to get node contents.
* 'callback' => callback to use to get node contents. e.g. array(&$anObject, 'methodName') or 'floatingMethod'
* 'autoPath' => array($left, $right $classToAdd = 'active']) if set any item in the path will have the class $classToAdd added. MPTT only.
* 'left' => name of the 'lft' field if not lft. only applies to MPTT data
* 'right' => name of the 'rght' field if not lft. only applies to MPTT data
* 'depth' => used internally when running recursively, can be used to override the depth in either mode.
* 'firstChild' => used internally when running recursively.
* 'splitDepth' => if multiple "parallel" types are required, instead of one big type, nominate the depth to do so here
* example: useful if you have 30 items to display, and you'd prefer they appeared in the source as 3 lists of 10 to be able to
* style/float them.
* 'splitCount' => the number of "parallel" types. defaults to 3
*
* @param array $data data to loop on
* @param array $settings
* @return string html representation of the passed data
* @access public
*/
public function generate($data, $settings = array ()) {
        $this->__settings = array_merge(array(
                'model' => 'Category',
                'alias' => 'name',
                'type' => 'ul',
                'itemType' => 'li',
                'id' => false,
                'class' => 'navsub',
                'element' => false,
                'callback' => false,
                'autoPath' => false,
                'left' => 'lft',
                'right' => 'rght',
                'depth' => 0,
                'firstChild' => true,
                'indent' => null,
                'splitDepth' => false,
                'splitCount' => 3,
            ), (array)$settings);
        if ($this-> __settings'autoPath'] && !isset($this->__ settings'autoPath'][2])) {
            $this->__settings'autoPath'][2] = 'active';
        }
        extract($this->__settings);
        if ($indent === null && Configure::read('debug')) {
            $indent = true;
        }
        $view =& ClassRegistry:: getObject('view');
        if ($model === null) {
            $model = Inflector::classify($view->params'models'][0]);
        }
        if (!$model) {
            $model = '_NULL_';
        }
        $stack = array();
        if ($depth == 0) {
            if ($class) {
                $this->addTypeAttribute('class', $class, null, 'previous');
            }
            if ($id) {
                $this->addTypeAttribute('id', $id, null, 'previous');
            }
        }
        $return = '';
        if ($indent) {
            $return = "\r\n";
        }
        $__addType = true;
        foreach ($data as $i => $result) {
            /* Allow 2d data arrays */
            if ($model == '_NULL_') {
                $_result = $result;
                $result$model] = $_result;
            }
            /* BulletProof */
            if (!isset($result$model]$left]) && !isset($result'children'])) {
                $result'children'] = array();
            }
            /* Close open items as appropriate */
            while ($stack && ($stack[count($stack)-1] < $result$model]$right])) {
                array_pop($stack);
                if ($indent) {
                    $whiteSpace = str_repeat("\t",count($stack));
                    $return .= "\r\n" . $whiteSpace . "\t";
                }
                if ($type) {
                    $return .= '</' . $type . '>';
                }
                if ($itemType) {
                    $return .= '</' . $itemType . '>';
                }
            }
            /* Some useful vars */
            $hasChildren = $firstChild = $lastChild = $hasVisibleChildren = false;
            $numberOfDirectChildren = $numberOfTotalChildren = null;
            if (isset($result'children'])) {
                if ($result'children']) {
                    $hasChildren = $hasVisibleChildren = true;
                    $numberOfDirectChildren = count($result'children']);
                }
                $prevRow = prev($data);
                if (!$prevRow) {
                    $firstChild = true;
                }
                next($data);
                $nextRow = next($data);
                if (!$nextRow) {
                    $lastChild = true;
                }
                prev($data);
            } elseif (isset($result$model]$left])) {
                if ($result$model]$left] != ($result$model]$right] - 1)) {
                    $hasChildren = true;
                    $numberOfTotalChildren = ($result$model]$right] - $result$model]$left] - 1) / 2;
                    if (isset($data$i + 1]) && $data$i + 1]$model]$right] < $result$model]$right]) {
                        $hasVisibleChildren = true;
                    }
                }
                if (!isset($data$i - 1]) || ($data$i - 1]$model]$left] == ($result$model]$left] - 1))) {
                    $firstChild = true;
                }
                if (!isset($data$i + 1]) || ($stack && $stack[count($stack) - 1] == ($result$model]$right] + 1))) {
                    $lastChild = true;
                }
            }
            $elementData = array(
                'data' => $result,
                'depth' => $depth ? $depth : count($stack),
                'hasChildren' => $hasChildren,
                'numberOfDirectChildren' => $numberOfDirectChildren,
                'numberOfTotalChildren' => $numberOfTotalChildren,
                'firstChild' => $firstChild,
                'lastChild' => $lastChild,
                'hasVisibleChildren' => $hasVisibleChildren
            );
            $this-> __settings = array_merge($this->__ settings, $elementData);
            /* Main Content */
            if ($element) {
                $content = $view->element($element, $elementData);
            } elseif ($callback) {
                list($content) = array_map($callback, array($elementData));
            } else {
                $content = $result$model]$alias];
            }
            if (!$content) {
                continue;
            }
            $whiteSpace = str_repeat("\t", $depth);
            if ($indent && strpos($content, "\r\n", 1)) {
                $content = str_replace("\r\n", "\n" . $whiteSpace . "\t", $content);
            }
            /* Prefix */
            if ($__addType) {
                if ($indent) {
                    $return .= "\r\n" . $whiteSpace;
                }
                if ($type) {
                    $typeAttributes = $this->__attributes($type, array('data' => $elementData));
                    $return .= '<' . $type . $typeAttributes . '>';
                }
            }
            if ($indent) {
                $return .= "\r\n" . $whiteSpace . "\t";
            }
            if ($itemType) {
                $itemAttributes = $this->__attributes($itemType, $elementData);
                $return .= '<' . $itemType . $itemAttributes . '>';
            }
            $return .= $content;
            /* Suffix */
            $__addType = false;
            if ($hasVisibleChildren) {
                if ($numberOfDirectChildren) {
                    $settings'depth'] = $depth + 1;
                    $return .= $this->__suffix();
                    $return .= $this->generate($result'children'], $settings);
                    if ($itemType) {
                        $return .= '</' . $itemType . '>';
                    }
                } elseif ($numberOfTotalChildren) {
                    $__addType = true;
                    $stack] = $result$model]$right];
                }
            } else {
                if ($itemType) {
                    $return .= '</' . $itemType . '>';
                }
                $return .= $this->__suffix();
            }
        }
        /* Cleanup */
        while ($stack) {
            array_pop($stack);
            if ($indent) {
                $whiteSpace = str_repeat("\t",count($stack));
                $return .= "\r\n" . $whiteSpace . "\t";
            }
            if ($type) {
                $return .= '</' . $type . '>';
            }
            if ($itemType) {
                $return .= '</' . $itemType . '>';
            }
        }
        if ($indent) {
            $return .= "\r\n";
        }
        if ($type) {
            $return .= '</' . $type . '>';
            if ($indent) {
                $return .= "\r\n";
            }
        }
        return $return;
}
/**
* addItemAttribute function
*
* Called to modify the attributes of the next <item> to be processed
* Note that the content of a 'node' is processed before generating its wrapping <item> tag
*
* @param string $id
* @param string $key
* @param mixed $value
* @access public
* @return void
*/
public function addItemAttribute($id = '', $key = '', $value = null) {
        if (!is_null($value)) {
            $this->__itemAttributes$id]$key] = $value;
        } elseif (!(isset($this-> __itemAttributes$id]) && in_array($key, $this->__ itemAttributes$id]))) {
            $this->__itemAttributes$id]] = $key;
        }
}
/**
* addTypeAttribute function
*
* Called to modify the attributes of the next <type> to be processed
* Note that the content of a 'node' is processed before generating its wrapping <type> tag (if appropriate)
* An 'interesting' case is that of a first child with children. To generate the output
* <ul> (1)
* <li>XYZ (3)
* <ul> (2)
* <li>ABC...
* ...
* </ul>
* ...
* The processing order is indicated by the numbers in brackets.
* attributes are allways applied to the next type (2) to be generated
* to set properties of the holding type - pass 'previous' for the 4th param
* i.e.
* // Hide children (2)
* $tree->addTypeAttribute('style', 'display', 'hidden');
* // give top level type (1) a class
* $tree->addTypeAttribute('class', 'hasHiddenGrandChildren', null, 'previous');
*
* @param string $id
* @param string $key
* @param mixed $value
* @access public
* @return void
*/
public function addTypeAttribute($id = '', $key = '', $value = null, $previousOrNext = 'next') {
        $var = '__typeAttributes';
        $firstChild = isset($this-> __settings'firstChild'])?$this->__ settings'firstChild']:true;
        if ($previousOrNext == 'next' && $firstChild) {
            $var = '__typeAttributesNext';
        }
        if (!is_null($value)) {
            $this->{$var}$id]$key] = $value;
        } elseif (!(isset($this->{$var}$id]) && in_array($key, $this->{$var}$id]))) {
            $this->{$var}$id]] = $key;
        }
    }
/**
* supressChildren method
*
* @return void
* @access public
*/
public function supressChildren() {
    }
/**
* suffix method
*
* Used to close and reopen a ul/ol to allow easier listings
*
* @access private
* @return void
*/
private function __suffix() {
        static $__splitCount = 0;
        static $__splitCounter = 0;
        extract($this->__settings);
        if ($splitDepth) {
            if ($depth == $splitDepth -1) {
                $total = $numberOfDirectChildren?$numberOfDirectChildren:$numberOfTotalChildren;
                if ($total) {
                    $__splitCounter = 0;
                    $__splitCount = $total / $splitCount;
                    $rounded = (int)$__splitCount;
                    if ($rounded < $__splitCount) {
                        $__splitCount = $rounded + 1;
                    }
                }
            }
            if ($depth == $splitDepth) {
                $__splitCounter++;
                if ($type && ($ __splitCounter % $__ splitCount) == 0) {
                    return '</' . $type . '><' . $type . '>';
                }
            }
        }
        return;
    }
/**
* attributes function
*
* Logic to apply styles to tags.
*
* @param mixed $rType
* @param array $elementData
* @access private
* @return void
*/
private function __attributes($rType, $elementData = array(), $clear = true) {
        extract($this->__settings);
        if ($rType == $type) {
            $attributes = $this->__typeAttributes;
            if ($clear) {
                $this-> __typeAttributes = $this->__ typeAttributesNext;
                $this->__typeAttributesNext = array();
            }
        } else {
            $attributes = $this->__itemAttributes;
            $this->__itemAttributes = array();
            if ($clear) {
                $this->__itemAttributes = array();
            }
        }
        if ($autoPath && $depth) {
            if ($this-> __settings'data']$model]$left] < $autoPath[0] && $this->__ settings'data']$model]$right] > $autoPath[1]) {
                $attributes'class']] = $autoPath[2];
            } elseif (isset($autoPath[3]) && $this->__settings'data']$model]$left] == $autoPath[0]) {
                $attributes'class']] = $autoPath[3];
            }
        }
        if ($attributes) {
            foreach ($attributes as $type => $values) {
                foreach ($values as $key => $val) {
                    if (is_array($val)) {
                        $attributes$type]$key] = '';
                        foreach ($val as $vKey => $v) {
                            $attributes$type]$key]$vKey] .= $vKey . ':' . $v;
                        }
                        $attributes$type]$key] = implode(';', $attributes$type]$key]);
                    }
                    if (is_string($key)) {
                        $attributes$type]$key] = $key . ':' . $val . ';';
                    }
                }
                $attributes$type] = $type . '="' . implode(' ', $attributes$type]) . '"';
            }
            return ' ' . implode(' ', $attributes);
}
return '';
}
}
?>

J'ai fait un debug afin de voir le tableau qu'il génère

app\View\Elements\nav.ctp (line 14)
Array
(
    [0] => Array
        (
            [Category] => Array
                (
                    [id] => 2
                    [name] => Couture
                    [slug] => couture
                    [lft] => 1
                    [rght] => 2
                    [parent_id] => 0
                    [link] => Array
                        (
                            [controller] => posts
                            [action] => category
                            [slug] => couture
                        )
                )
        )
    [1] => Array
        (
            [Category] => Array
                (
                    [id] => 3
                    [name] => Cartonnage
                    [slug] => cartonnage
                    [lft] => 11
                    [rght] => 12
                    [parent_id] => 0
                    [link] => Array
                        (
                            [controller] => posts
                            [action] => category
                            [slug] => cartonnage
                        )
                )
        )

MON SOUCI est que je n'arrive pas à lier les catégories aux posts, quand je passe la souris sur un lien il me met posts/category, alors qu'il devrait m'ajouter le nom de la catégorie

Comment faire pour corriger tout ca? merci de votre aide

5 réponses


karmalo
Auteur
Réponse acceptée

C'est bon tout est résolu

Dans le tuto, ils mettent ainsi

echo $html->link(
    $data'Category']'libelle'],
    array(
        'controller' => 'categories',
        'action' => 'view',
        $data'Category']'id']
    )
);

Comme avec le tuto de grafikart, on génère les slugs, il faut mettre ceci à la place

<?php echo $this->Html->link($data'Category']'name'], $data'Category']'link']); ?>

Oula bcp de code là tu peux juste montrer ce que tu as/ ce que tu voudrais avoir ?

karmalo
Auteur

Avec le TreeHelper, il me génère bien le menu avec ul et li. Dans nav.ctp, j'ai ajouté le <a href> pour que la catégorie devienne un lien. et dans celui-ci, j'aurais voulu mettre $cat'Category']'link'], mais ca ne fonctionne pas car vu le debug, on s'aperçoit que c'est un tableau dans un tableau.

J'ai vu ce code là treeheleper

Et je constate qu'il utilise un extract ($data) mais ca je ne sais pas m'en servir.

Le souci, je m'aperçois que le lien qu'il génère actuellement est post/category, alors qu'il devrait me mettre category/(le nom de la catégorie)
Ainsi, quand je cliquerais sur la catégorie, ca affichera tous les posts liés à celui-ci

karmalo
Auteur

En regardant le code, je m'aperçois que le <a href> que j'ai mis dans nav.ctp n'est pas bon.

Donc, au final, je ne sais pas comment faire

karmalo
Auteur

J'ai vu le tuto arborescence

J'ai ma liste de catégories qui s'affiche correctement
J'ai suivi le tuto cakephp en 4 jours

Dans le TreeHelper version pour cakephp 2.0
A la ligne 141, j'ai modifié
$view =& ClassRegistry:: getObject('view');

A remplacer par:
$view =& $this->_View;

le souci que je rencontre, est que lorsqu'on clique sur une catégorie, qu'il affiche tous les posts liés à celle-ci.

Actuellement, le lien qu'il génère est le suivant:
http://localhost/blog/posts/index/posts/category/patchwork

Alors qu'il devrait être ainsi:
http://localhost/blog/categorie/patchwork

merci de votre aide