Bonjour à tous,

Encore une fois, je viens demander de l'aide pour continuer sur les tutos des MVC.
J'aimerai créer un tableau de catégories de produits et des ses sous catégories (multi niveaux) mais je n'y arrive pas.

J'essaie de m'inspirer de ce tuto que j'ai trouvé sur le net.

http://www.experts-exchange.com/Internet/Web\_Development/A\_3224-Dynamic-Multi-level-CSS-Menu-with-PHP-and-MySQL-SEO-Ready.html

Pour me plier à la règle du MVC, j'ai crée une fonction qui me permet de retourner un array avec les catégories de même niveau. (pour les noms de variables, j'ai appliqué bêtement ce qu'il a mis dans le tuto)

function getCategory($id) {
        // 1. on charge le model
        $this->loadModel('Categories');        
        // 2. on fait notre requete
        $req = array(
            'tables' => array(
                'category' => 'c'
            ),
            'fields' => array(
                'c' => 'id,name,content,online',
            ),
            'jointure' => 'c.id=Deriv1.parent_category_id',
            'enfant' => 'Deriv1',
            'parent' => array(
                'c'=>'parent_category_id'
            ),
            'conditions'=>$id
        );
        return $this->Categories->findParentCategory($req);

    }

Le souci c'est que dans la vue, je n'arrive pas à implémenter sa boucle while. (car pas MVC)
J'utilise des foreach, mais ceux-ci s'arrêtent au premier sous menu et ne vont pas au delà si je ne rajoute pas un nouveau foreach et ainsi de suite.

Voici le code de ma vue

<?php
$parent = 0;
$getCat = $this->request('Categories', "getCategory", $parent);
?>
<br/><br/><br/>
<?php foreach ($getCat as $k => $v) { ?>
    <ul>
        <?php if ($v->Count > 0) { ?>        
            <li><?php echo $v->name; ?>
                <!-- début de la boucle -->
                <?php $getCat$k] = $this->request('Categories', "getCategory", $v->id); debug($getCat) ?>
                <ul>
                    <?php foreach ($getCat$k] as $o => $u): ?>
                        <li><?php echo $u->name; ?></li>
                    <?php endforeach; ?>
                </ul>
                <!-- fin de la boucle -->
            </li>
        <?php } elseif ($v->Count == 0) { ?>
            <li><?php echo $v->name; ?></li>
        <?php } ?>
    </ul>
<?php } ?>

Autrement, j'ai ce post sur le forum, mais je n'arrive pas à trouver le tuto en question. Si vous savez quel tuto visionner, je suis preneur.

http://www.grafikart.fr/forum/topic/1649

Cordialement,

Fabien

9 réponses


fabienc
Auteur
Réponse acceptée

Eureka !!!
J'ai trouvé!
En fait, ma fonction de génération des listes était bonne, sauf à un endroit :
ici, je lui disais de reboucler sur la liste de départ, au lieu de boucler sur la liste "childs", et donc forcément, il ne trouvait rien.

$this->printArray($list,$list$i]->c_id);

Du coup la ca marche nickel, et voici ce que ca m'affiche !!!!

<ul>
<li>
Revêtements sols
<ul>
<li>
Carrelage
<ul>
</li>
</ul>
</li>
<li>
Menuiserie
<ul>
<li>Intérieure</li>
</ul>
</li>
<li>Porte</li>
<li>Platrerie et isolation</li>
</ul>

Bonjour,

Si j'ai bien compris tu as plusieurs niveaux :

Categorie -> Categorie -> Produit -> ...

-> Produit
-> ...

A ce moment là, pourquoi ne pas utiliser une récurrence qui va te permettre de rappeler ta méthode d'affichage à chaque nouveaux noeuds.
En gros :
Si tu es sur un produit -> affichage des informations produits
Sinon rappeler la méthode récurrente.

fabienc
Auteur

Salut,
Merci pour ton aide.
Je ne suis pas sûr d'avoir tout saisi.
En gros, je doit faire une fonction qui aura pour role de générer du code html selon une condition. Si on n'est plus dans la condition, on rappelle cette même fonction?

Je suis allé fouillé sur le net pour comprendre un peu mieux ce concept.
Néanmoins, je n'arrive pas à l'adapter au MVC. En effet, le but du MVC c'est de mettre tout le html dans les vues et toutes les fonctions dans les contrôler.

Si je suis ce que tu me dis, je devrais créer un fonction dans le controller, en charge de l'affichage de mon code HTML?
C'est bien ça!! ou bien je n'ai rien compris !

Fabien

fabienc
Auteur

j'ai trouvé ce tuto
http://crisp.tweakblogs.net/blog/317/formatting-a-multi-level-menu-using-only-one-query.html
je vais essayer de m'en inspirer pour avancer

fabienc
Auteur

Bon alors j'ai fouillé le web et je suis arrivé à ceci, une fonction que j'ai mis dans ma vue.
Pour le moment ca boucle à l'infini, mais je pense être sur la bonne voie

<?php
$parent = 0;
$getCat = $this->request('Categories', "getCategory", $parent);
//debug($this->nomController);
// on générer notre menu
function echo_menu($getCat,$parent) {
    //go through each top level menu item
    foreach($getCat as $menu=>$u) {
        //debug($getCat);
        echo "<li><a href='{$u->name}'>{$u->name}</a>";
        //see if this menu has children
        if($u->Count >0) {
            echo '<ul>';
            //echo the child menu
            echo_menu($getCat,$u->id);
            echo '</ul>';
        }
        echo '</li>';
    }
}
echo '<ul>';
debug($parent);
echo_menu($getCat,$parent);
debug($parent);
echo '</ul>';
?>
fabienc
Auteur

Bon alors j'ai fouillé le net et mixé plusieurs solutions. Je touche au but
Voici les deux fonctions que j'ai créé.

La première va mettre en forme le array que je récupère de la base de données, et la deuxième est censée (je dis bien censée) afficher mes listes avec leur hiérarchie (mais ne fonctionne pas en fait)

Ici je formate les infos qui viennent de la base

function makeArray(&$list, $parent = 0) {
        // prend comme argument un array
        $result = array();
        for ($i = 0, $c = count($list); $i < $c; $i++) {
            if ($list$i]->c_parent_category_id == $parent) {
                $list$i]->c_childs = $this->makeArray($list, $list$i]->c_id);
                $result] = $list$i];
            }
        }
        return $result;
    }

ici j'essaie de mettre en forme

function printArray(&$list, $parent = 0) {
        echo '<ul>';
        for ($i = 0, $c = count($list); $i < $c; $i++) {
            if ($list$i]->c_parent_category_id == $parent && $list$i]->c_parent_category_id != NULL) {
                echo '<li>' . $list$i]->c_name;
                if (!empty($list$i]->c_childs)) {
                    debug(((int)$list$i]->c_id));
                    //$this->printArray($list,$list$i]->c_id);
                }
                echo '</li>';
            }
        }
        echo '</ul>';
    }

Et ça c'est ce que j'ai collé dans ma vue

$getCat = $this->request("Categories", "getParentCategory");
//debug($getCat);
$makeArray = $this->request('Categories', 'makeArray', $getCat);
debug($makeArray);
$printArray = $this->request('Categories', 'printArray', $makeArray);

Malheureusement, cela ne génère même pas le premier sous niveau.

Voici pour exemple le tableau généré

Array
(
    [0] => stdClass Object
        (
            [c_id] => 1
            [c_name] => Revêtements sols
            [c_parent_category_id] => 0
            [c_childs] => Array
                (
                    [0] => stdClass Object
                        (
                            [c_id] => 2
                            [c_name] => Carrelage
                            [c_parent_category_id] => 1
                            [c_childs] => Array
                                (
                                    [0] => stdClass Object
                                        (
                                            [c_id] => 3
                                            [c_name] => Parquet
                                            [c_parent_category_id] => 2
                                            [c_childs] => Array
                                                (
                                                )
                                        )
                                )
                        )
                )
        )
    [1] => stdClass Object
        (
            [c_id] => 4
            [c_name] => Menuiserie
            [c_parent_category_id] => 0
            [c_childs] => Array
                (
                    [0] => stdClass Object
                        (
                            [c_id] => 6
                            [c_name] => Intérieure
                            [c_parent_category_id] => 4
                            [c_childs] => Array
                                (
                                )
                        )
                )
        )
    [2] => stdClass Object
        (
            [c_id] => 5
            [c_name] => Porte
            [c_parent_category_id] => 0
            [c_childs] => Array
                (
                )
        )
    [3] => stdClass Object
        (
            [c_id] => 10
            [c_name] => Platrerie et isolation
            [c_parent_category_id] => 0
            [c_childs] => Array
                (
                )
        )
    [4] => stdClass Object
        (
            [c_id] => 11
            [c_name] => 
            [c_parent_category_id] => 
            [c_childs] => Array
                (
                )
        )
)

Le fonction recurrente ne veut rien savoir !!
Si j'arrive à la faire fonctionner, cela va m'aider pour créer dynamiquement mes menus et gérer toutes les class en fonction, mais également faire mes listes de catégories de produit en toute simplicité.

Merci à tous pour votre aide !

Fabien

Bonjour,

Je pense qu'il faut que tu déclare ton tableau "result" hors de ta fonction makeArray. Tu peux par exemple le mettre comme paramètre sinon tu le redéclare à chaque fois que tu passe dans ta fonction.

fabienc
Auteur

Désolé mais je ne comprends pas ta réponse.
Pourquoi est-ce que je dois toucher à la variable $result qui se trouve dans ma fonction de mise en forme d'un array?
N'est ce pas du côté de ma fonction printArray() que l'erreur se trouve?
Je vais essayer de modifier selon tes suggestion.
Je te dirais que, impact sera aura.
Fabien

fabienc
Auteur

Juste voici la solution(je ne suis pas parvenu à modifie le précédent post)

$this->printArray($list$i]->c_childs,$list$i]->c_id);