Bonjour,
Je suis actuellement débutant sur Cake et je m'aide beaucoup de toute ces ressources. Donc tout d'abord, merci à Grafikart et à la communauté pour les tutos et pour vos aides précieuses. J'ai cherché dans le forum et je n'ai pas trouvé de solution à mon problème.

Dans l’administration, je cherche à hiérarchiser mes pages et je souhaiterais que certaines pages aient une page parente.
Dans ma BDD, j'ai une table "pages" avec les champs :

id
name
slug
content
type
media_id
online
display_menu
parent_id
created
modfied

Je créé mes pages à l'aide de l'administration et dans ma BDD, le "type" devient "page". Cette partie fonctionne. Si je veux qu'une page devienne parente, je fais appel à la fonction admin_parent.
Le menu déroulant qui hiérarchise les pages fonctionne, mais je n'arrive pas à changer dans la BDD le "type""page" en "subpage" et à mettre une id dans "parent_id". Auriez-vous une petite idée ?

Voici le PagesContoller.php :

<?php
App::uses('AppController', 'Controller');
class PagesController extends AppController {
    public $uses = array('Page'); 
    /**
    * ADMIN
    **/
    public function admin_index() {
        $d'pages'] = $this->Page->find('all', array(
            'conditions' => array('type' => array('page', 'subpage'), 'online >= 0'),
            'order' => 'Page.id DESC'
        ));
        $this->set($d);
    }   
    public function admin_edit($id = null) {
        $d'pagesList'] = $this->Page->find('list', array(
            'conditions' => array('type' => 'page', 'parent_id' => null)
        ));
        $this->helpers] = 'Media.Uploader'; 
        if (!empty($this->request->data)) {
            if (!empty($this->request->data'Page']'id'])) {
                $this->request->data'Page']'type'] = 'page'; 
                $this->Page->id = $this->request->data'Page']'id']; 
                if ($this->Page->save($this->request->data)) {
                    $this->Session->setFlash("La page a été ajoutée !","notif", array('type'=>'success'));
                    $this->redirect(array('action' => 'index'));
                }
            }
        }
        if ($id) {
            $this->request->data = $this->Page->find('first', array(
                'conditions' => array('Page.id' => $id)
            ));
        } else {
            $this->request->data = $this->Page->getDraft(); 
        }
        $this->loadModel('File'); 
        $d'files'] = $this->File->find('all', array(
            'conditions' => array('ref' => 'Page', 'ref_id' => $this->request->data'Page']'id'])
        ));
        $this->set($d);
    }
    public function admin_parent($id) {
        if (!empty($this->request->query)) {
            $this->Page->id = $id; 
            $this->Page->saveField('parent_id', key($this->request->query)); 
            $this->Page->saveField('type', 'subpage'); 
        }
        $page = $this->Page->find('first', array(
            'conditions' => array('Page.id' => $id, 'Page.type' => 'subpage')
        ));
        $d'parent_page'] = $this->Page->find('first', array(
            'conditions' => array('Page.id' => $page'Page']'parent_id'], 'type' => 'page'),
            'fields' => array('id', 'name')
        ));
        $d'pagesList'] = $this->Page->find('list', array(
            'conditions' => array('Page.type' => 'page', 'Page.parent_id' => null, 'Page.id !=' => $id)
        ));
        $this->set($d);
    }
}

Voici le admin_parent.ctp :

<?php echo $this->Form->create('Page', array('id' => 'parentForm')); ?>
<?php echo $this->Form->input('parent_id',array('label'=>"Page parente :", 'options' => $pagesList)); ?>
<div class="spacer30"></div>
<?php echo $this->Form->end('Valider'); ?>

admin.js :

$('.editCreatedShow').hide(); 
    $('.editCreated').live('click', function(event){
        elem = $(this).parent().find('.editCreatedShow'); 
        if ( elem.hasClass( 'showing' ) ) {
            $(this).removeClass('btn-warning').text("Modifier la date de création"); 
            elem.removeClass('showing').fadeOut('fast'); 
        } else {
            $(this).addClass('btn-warning').text('Ne pas modifier'); 
            elem.addClass('showing').fadeIn('fast'); 
        }
        return false; 
    });
    $('#parentForm').submit(function(event){
        form = $(this); 
        data = form.find('#PostParentId').val(); 
        url = form.attr('action'); 

        $.ajax({
            data: data, 
            url: url
        });
        event.preventDefault(); 
    });

Pour info, j'obtiens une erreur : Notice (8): Undefined index: Page [APP\Controller\PagesController.php, line 72]
qui correspond à

'conditions' => array('Page.type' => 'page', 'Page.parent_id' => null, 'Page.id !=' => $id)

je vous remercie par avance.

4 réponses


zacra
Auteur
Réponse acceptée

Finalement j'ai apporté quelques modifications à ma BDD :

id
name
slug
content
media_id
online
display_menu
parent_id
<strong>lft</strong>
<strong>rght</strong>
created
modfied

La création et l'organisation des pages s'effectuent par la méthode : generateTreeList.

Mon menu principal est généré via MenuController :

...
$d'sous_menu'] = $this->Page->find('all', array(
    'conditions' => array( 'online' => true,'parent_id'=>$page'Page']'id'])
    ));
$d'page'] = $page; 
$this->set($d);
}

et à mon index.ctp :

<?php if (!empty($sous_menu)): ?>
        <ul class="list">
            <?php foreach ($sous_menu as $k => $v): $v = current($v); ?>
                <li><?php echo $this->Html->link($v'name'], $v'link']); ?></li>
            <?php endforeach ?>
        </ul>
<?php endif ?>

Bref, si j'ai des pages enfants, alors les liens s'affiche en fonction de la page courante.

zacra
Auteur
Réponse acceptée

Allez je continue avec mon menu et mon filtre de parents/enfants.
Voici l'évolution de mon PostsController qui affiche mon sous-menu que si la page active possède des enfants ou si la page active est un enfant.

$d'sous_menu'] = $this->Page->find('all', array(
                'conditions' => array( 'online' => true,"OR" => array(
                    'parent_id'=>$page'Page']'id'],
                    "AND" => array('parent_id'=>$page'Page']'parent_id'], 'parent_id !=' => NULL)
                ))
        ));

            $d'page'] = $page; 
            $this->set($d);
        }

Vérifie que ton Model Page est correctement défini tu doit avoir un Has_many

'ChildPost' => array(
            'className' => 'Page',
            'foreignKey' => 'parent_id',
            'dependent' => false,
            'conditions' => '',
            'fields' => '',
            'order' => '',
            'limit' => '',
            'offset' => '',
            'exclusive' => '',
            'finderQuery' => '',
            'counterQuery' => ''
        )

et un belongsTo

'ParentPost' => array(
            'className' => 'Page',
            'foreignKey' => 'parent_id',
            'conditions' => '',
            'fields' => '',
            'order' => ''
        ),

Pour le reste je trouve bizarre ta gestion et action des parents (admin_parent) en principe c'est cake qui gère la mise en place d'un père ou non et toi dans les actions admin_edit et admin_add, toi de ton coté si tu veux ce que tu appelle les page de type page tu as juste à recherche avec la condition

'conditions' => array('Page.parent_id' => null)

et non les deux qui en faite représente la même chose 'Page.type' => 'page', 'Page.parent_id' => null

le plus c'est par exemple dans l'affichage des parents faire un autocomplete pour éviter le jour ou tu auras 500 Pages d'avoir dans ton formulaire une liste avec 500 éléments
.
J'espère que ca t'aidera :)

zacra
Auteur

Merci de ta réponse BenFarhat.
Je n'avais aucun belongsTo ni de hasMany dans mon Model Post.php

J'ai donc rajouté :

public $hasMany = array(
        'ChildPost' => array(
            'className' => 'Page',
            'foreignKey' => 'parent_id',
            'dependent' => false,
            'conditions' => '',
            'fields' => '',
            'order' => '',
            'limit' => '',
            'offset' => '',
            'exclusive' => '',
            'finderQuery' => '',
            'counterQuery' => ''
        )
    );
    public $belongsTo = array(
        'ParentPost' => array(
            'className' => 'Page',
            'foreignKey' => 'parent_id',
            'conditions' => '',
            'fields' => '',
            'order' => ''
        )
    );

Si j'ai bien compris, tu me conseilles de remplacer :

'conditions' => array('Page.type' => 'page', 'Page.parent_id' => null, 'Page.id !=' => $id)

par

'conditions' => array('Page.type' => 'page', 'Page.id !=' => $id)

Dans tous les cas, j'ai toujours la même erreur, voir même, le résultat est pire car j'obtiens une erreur sql :

Error: SQLSTATE[23000]: Integrity constraint violation: 1052 Column 'type' in where clause is ambiguous
SQL Query: SELECT `Page`.`id`, `Page`.`name` FROM `gaulenew`.`pages` AS `Page` LEFT JOIN `gaulenew`.`pages` AS `ParentPost` ON (`Page`.`parent_id` = `ParentPost`.`id`) LEFT JOIN `gaulenew`.`medias` AS `Thumb` ON (`Page`.`media_id` = `Thumb`.`id`) WHERE `Page`.`id` IS NULL AND `type` = 'page' LIMIT 1

Pour répondre à ton interrogation sur la raison de cette gestion, c'est que je souhaite créer un menu dynamique en fonction des pages principales (parent) et un sous-menu avec les pages enfants.
Ex:
A. Page parent : "Informations" avec un résumé des actualités des pages enfants.
a. Page enfant : thématique 1

  • Avec des articles
    b. Page enfant : thématique 2...