Bonjour,

Voila j'aurais une petite question !

J'ai une table "droits" qui possède trois champs : profil_id, application_id et name. Profil_id et application_id sont respectivement les clés étrangères des tables "Profiles" et "Applications", et également la clé primaire concaténée de la table "droits".

Je souhaiterais, dans ma vue, afficher le champs "name", en fonction du profil_id et de l'application_id, mais je ne vois pas comment faire. J'essaie de m'aider du code généré automatiquement par Cake (ci-dessous), mais je n'arrive pas à faire ce que je veux.

// Dans la vue index.ctp du controller Droits, code généré par CakePHP

<table cellpadding="0" cellspacing="0">
        <thead>
            <tr>
                <th><?= $this->Paginator->sort('profil_id') ?></th>
                <th><?= $this->Paginator->sort('application_id') ?></th>
                <th><?= $this->Paginator->sort('name') ?></th>
                <th class="actions"><?= __('Actions') ?></th>
            </tr>
        </thead>
        <tbody>
            <?php foreach ($droits as $droit): ?>
            <tr>
                <td><?= $this->Number->format($droit->profil_id) ?></td>
                <td><?= $droit->has('application') ? $this->Html->link($droit->application->name, ['controller' => 'Applications', 'action' => 'view', $droit->application->id]) : '' ?></td>
                <td><?= $this->Number->format($droit->name) ?></td>
                <td class="actions">
                    <?= $this->Html->link(__('View'), ['action' => 'view', $droit->profil_id]) ?>
                    <?= $this->Html->link(__('Edit'), ['action' => 'edit', $droit->profil_id]) ?>
                    <?= $this->Form->postLink(__('Delete'), ['action' => 'delete', $droit->profil_id], ['confirm' => __('Are you sure you want to delete # {0}?', $droit->profil_id)]) ?>
                </td>
            </tr>
            <?php endforeach; ?>
        </tbody>
    </table>

Par exemple, sur ce morceau de code, $droit->application->name m'affiche bien le nom de l'application. Mais je n'arrive pas à comprendre comment.
De plus, à quoi sert le "$droit->has('application')" ?

Merci pour votre aide, en espérant avoir été assez claire sur mon soucis ^^'

Ju'

17 réponses


Anju
Auteur
Réponse acceptée

Désolée pour le temps de réponse, j'avais un peu oublié ce sujet.
Mais du coup, j'ai réglé mon problème en modifiant ma table Profils.

Maintenant ma table Profils a plusieurs champs :
id, name, role_admin, role_news, etc.
Comme ça, on sait directement en BDD les droits des utilisateurs, et tout est plus simple, pour moi en tout cas :)

Merci pour votre aide ^^

Bonjour,
Fais une coupe de debug($droits) cela apportera pas mal de réponse à tes questions. Sinon je te conseille d'aller sur la doc de Cake pour bien comprendre le fonctionnement du framework.

Anju
Auteur

Bonjour, merci de ta réponse !

Je ne comprends pas trop ce que tu veux dire :/
J'ai fais un debug($this->Droits), ce qui me renvoie ceci :

object(App\Model\Table\DroitsTable) {
    'registryAlias' => 'Droits',
    'table' => 'droits',
    'alias' => 'Droits',
    'entityClass' => 'App\Model\Entity\Droit',
    'associations' => [
        (int) 0 => 'profiles',
        (int) 1 => 'applications'
    ],
    'behaviors' => [],
    'defaultConnection' => 'default',
    'connectionName' => 'default'
}

Quand je fais un debug($this->Droits->profiles, ça me renvoie ça :

object(Cake\ORM\Association\BelongsTo) {
    [protected] _validStrategies => [
        (int) 0 => 'join',
        (int) 1 => 'select'
    ]
    [protected] _name => 'Profiles'
    [protected] _className => null
    [protected] _bindingKey => 'id'
    [protected] _foreignKey => 'profil_id'
    [protected] _conditions => []
    [protected] _dependent => false
    [protected] _cascadeCallbacks => false
    [protected] _sourceTable => object(App\Model\Table\DroitsTable) {

        'registryAlias' => 'Droits',
        'table' => 'droits',
        'alias' => 'Droits',
        'entityClass' => 'App\Model\Entity\Droit',
        'associations' => [
            (int) 0 => 'profiles',
            (int) 1 => 'applications'
        ],
        'behaviors' => [],
        'defaultConnection' => 'default',
        'connectionName' => 'default'

    }
    [protected] _targetTable => object(App\Model\Table\ProfilesTable) {

        'registryAlias' => 'Profiles',
        'table' => 'profiles',
        'alias' => 'Profiles',
        'entityClass' => 'App\Model\Entity\Profile',
        'associations' => [],
        'behaviors' => [],
        'defaultConnection' => 'default',
        'connectionName' => 'default'

    }
    [protected] _joinType => 'INNER'
    [protected] _propertyName => 'profile'
    [protected] _strategy => 'join'
    [protected] _finder => 'all'
    [protected] _tableLocator => object(Cake\ORM\Locator\TableLocator) {
        [protected] _config => []
        [protected] _instances => [
            'Droits' => object(App\Model\Table\DroitsTable) {

                'registryAlias' => 'Droits',
                'table' => 'droits',
                'alias' => 'Droits',
                'entityClass' => 'App\Model\Entity\Droit',
                'associations' => [
                    (int) 0 => 'profiles',
                    (int) 1 => 'applications'
                ],
                'behaviors' => [],
                'defaultConnection' => 'default',
                'connectionName' => 'default'

            },
            'Profiles' => object(App\Model\Table\ProfilesTable) {

                'registryAlias' => 'Profiles',
                'table' => 'profiles',
                'alias' => 'Profiles',
                'entityClass' => 'App\Model\Entity\Profile',
                'associations' => [],
                'behaviors' => [],
                'defaultConnection' => 'default',
                'connectionName' => 'default'

            },
            'Applications' => object(App\Model\Table\ApplicationsTable) {

                'registryAlias' => 'Applications',
                'table' => 'applications',
                'alias' => 'Applications',
                'entityClass' => 'App\Model\Entity\Application',
                'associations' => [
                    (int) 0 => 'droits'
                ],
                'behaviors' => [],
                'defaultConnection' => 'default',
                'connectionName' => 'default'

            }
        ]
        [protected] _fallbacked => []
        [protected] _options => [
            'Droits' => [],
            'Profiles' => [
                'className' => null
            ],
            'Applications' => [
                'className' => null
            ]
        ]
    }
}

Pareil pour applications au lieu de profiles. Mais je ne comprends toujours pas comment récupérer une ligne de ma table :(
Je vais retourner voir la doc, encore, mais si tu peux m'aider encore peu ce serait très gentil :$

Non je te demandais de faire le debug dans ta vue :

// dans index.ctp
<?= debug($droits) ; ?>

Cela te permettra de voir que contient la varaible $droits et de voir la structure des objets.

Quelle est la requête que tu fais dans l'action de ton controlleur pour récupérer la liste des droits ?

Anju
Auteur

Ah pardon j'avais mal compris !

Du coup ça me renvoie ceci :

object(Cake\ORM\ResultSet) {

    'query' => object(Cake\ORM\Query) {

        '(help)' => 'This is a Query object, to get the results execute or iterate it.',
        'sql' => 'SELECT Droits.profil_id AS `Droits__profil_id`, Droits.application_id AS `Droits__application_id`, Droits.name AS `Droits__name`, Profiles.id AS `Profiles__id`, Profiles.name AS `Profiles__name`, Applications.id AS `Applications__id`, Applications.name AS `Applications__name`, Applications.description AS `Applications__description` FROM droits Droits INNER JOIN profiles Profiles ON Profiles.id = (Droits.profil_id) INNER JOIN applications Applications ON Applications.id = (Droits.application_id) LIMIT 20 OFFSET 0',
        'params' => [],
        'defaultTypes' => [
            'Droits.profil_id' => 'integer',
            'profil_id' => 'integer',
            'Droits.application_id' => 'integer',
            'application_id' => 'integer',
            'Droits.name' => 'string',
            'name' => 'string',
            'Profiles.id' => 'integer',
            'id' => 'integer',
            'Profiles.name' => 'string',
            'Applications.id' => 'integer',
            'Applications.name' => 'string',
            'Applications.description' => 'text',
            'description' => 'text'
        ],
        'decorators' => (int) 0,
        'executed' => true,
        'hydrate' => true,
        'buffered' => true,
        'formatters' => (int) 0,
        'mapReducers' => (int) 0,
        'contain' => [
            'Profiles' => [],
            'Applications' => []
        ],
        'matching' => [],
        'extraOptions' => [
            'whitelist' => [
                (int) 0 => 'limit',
                (int) 1 => 'sort',
                (int) 2 => 'page',
                (int) 3 => 'direction'
            ]
        ],
        'repository' => object(App\Model\Table\DroitsTable) {

            'registryAlias' => 'Droits',
            'table' => 'droits',
            'alias' => 'Droits',
            'entityClass' => 'App\Model\Entity\Droit',
            'associations' => [
                (int) 0 => 'profiles',
                (int) 1 => 'applications'
            ],
            'behaviors' => [],
            'defaultConnection' => 'default',
            'connectionName' => 'default'

        }

    },
    'items' => [
        (int) 0 => object(App\Model\Entity\Droit) {

            'profil_id' => (int) 2,
            'application_id' => (int) 1,
            'name' => 'administrateur',
            'application' => object(App\Model\Entity\Application) {

                'id' => (int) 1,
                'name' => 'News',
                'description' => 'Application d échange et de news',
                '[new]' => false,
                '[accessible]' => [
                    '*' => true
                ],
                '[dirty]' => [],
                '[original]' => [],
                '[virtual]' => [],
                '[errors]' => [],
                '[repository]' => 'Applications'

            },
            'profile' => object(App\Model\Entity\Profile) {

                'id' => (int) 2,
                'name' => 'DP',
                '[new]' => false,
                '[accessible]' => [
                    '*' => true
                ],
                '[dirty]' => [],
                '[original]' => [],
                '[virtual]' => [],
                '[errors]' => [],
                '[repository]' => 'Profiles'

            },
            '[new]' => false,
            '[accessible]' => [
                '*' => true
            ],
            '[dirty]' => [],
            '[original]' => [],
            '[virtual]' => [],
            '[errors]' => [],
            '[repository]' => 'Droits'

        },       

        ]

}

(Etc avec une totalité de 20 items (je suis censée en avoir 25 dans ma base...)

Voici ma fonction index.php :

public function index()
    {
        $this->paginate = [
            'contain' => ['Profiles', 'Applications']
        ];
        $this->set('droits', $this->paginate($this->Droits));
        $this->set('_serialize', ['droits']);

    }

Cette fonction m'affiche un tableau de trois colonnes correspondant aux champs de la table Droits.

ok, le debug que tu as fais n'est pas le résultat e la requête mais la requête : fais debug($droits->toArray()); dans ton ctp pour exécuter la requête et voir le résultat.
Après je ne comprends pas trop ce que tu demandes sur name peux tu préciser ?

Anju
Auteur

Du coup, avec le debug($droits->toArray()); ça me renvoie un tableau de mes entrées dans ma table Droits, comme le précédent résultat, mais sans la requête en fait :o (à partir du "(int) 0").

Donc par exemple dans ce tableau, je voudrais que dans la case News/DP, le droit qui correspond s'affiche.
Dans ma table droits ça correspondrait à ça : profil_id = 2, application_id = 1, name = administrateur.
J'aimerais que le droit "administrateur" apparaisse dans la case.
Et ainsi de suite pour les autres cases du tableau !

Pardon pour le debug, j'avais pas vu.
Je ne comprends pas ce que tu demandes car sinon c'est tout simple :

// dans la boucle foreach
<?= $droit->profil_id; ?>// profil_id
<?= $droit->application_id; ?> // application_id
<?= $droit->name; ?> // name
// etc

Je ne vois pas ce qu'il te dérange ou où est le problème ?

Anju
Auteur

Hum... C'est pas tout à fait ça que je veux ^^'

En fait mon vrai tableau c'est ça (l'autre code c'était ce qui était généré par CakePHP):

<table cellpadding="0" cellspacing="0">
                        <thead>
                            <tr>                          
                                <th>DP</th>
                                <th>CP</th>
                                <th>Référent</th>
                                <th>Sachant</th>
                                <th>Intervenant</th>
                                <th>MOE</th>
                            </tr>
                        </thead>
                        <tbody>
                            <tr>
                                <th>News</th>
                                <td><? ?></td>
                                <td><?  ?></td>
                            </tr>
                            <tr>
                                <th>Agenda</th>
                            </tr>
                        </tbody>
                    </table>

Et en gros dans le td après News, je voudrais le name de la table Droits qui correspond :/
Un truc du genre $droits['profil_id' = 2, 'application_id' = 1]->name; Bon ça veut surement rien dire ça, mais c'est en gros ce que j'aimerais :/

En fait ce qui me gêne c'est le fait que ce soit un tableau à double entrée :/

Le cas $droits['profil_id' = 2, 'application_id' = 1]->name correspond au premier $droit de ta boucle foreach, donc c'est ce que tu veux !!!
Soit je ne comprend rien à ce que tu me dis, soit tu ne te fais pas bien comprendre.
Quel est ton niveau en php ? cake ?

Après si tu veux récupérer les droits où ['profil_id' = 2, 'application_id' = 1], c'est dans ton controlleur qu'il faut changer :

$query = $this->Droits->find()
                       ->where(['Droits.profil_id' => 2, 'Droits.application_id' => 1])
                       ->contain(['Profiles', 'Applications']);
$this->set('droits', $this->paginate(query ));
$this->set('_serialize', ['droits']);
Anju
Auteur

Désolée, je dois mal me faire comprendre ^^'
Avec un foreach, ça me ressort une liste de tous les droits. D'accord, c'est ce que je veux ! Mais après, comment les placer au bon endroit dans mon tableau ?
Ca semble un peu bête comme question dit comme ça, mais j'ai du mal à visualiser :s

Et bien tout simplement en faisant appel aux propriétés/champs de tes objets :

$droit->profil_id; // equivalent  à $droit->profil->id
$droit->application_id; // equivalent  à $droit->application->id
$droit->name;
$droit->application->name;
$droit->profil->name;
//etc ...

Quels champs veux tu dans chaque case ?

Anju
Auteur

C'est bizarre tout fonctionne sauf $droit->profil->name qui me renvoie une erreur "Notice (8): Trying to get property of non-object [APP/Template\Droits\index.ctp, line 65]". Sinon les autres renvoient bien les bonnes données.

Dans chaque case je veux le champs "name" de la table Droits, correspondant aux entrées de mon tableau. Genre dans ma case qui correspond à News et DP, je veux le name qui correspond à la clé primaire (2,1) (2 pour le DP et 1 pour le News)!

Le problème c'est que comme pour Application, certains de tes Droits ne sont pas associés à un Profil, donc tu dois mettre une condition pour voir si la propriété profil existe dans ton droit avant d'y accéder.

$droit->has('profil') ? $droit->profil->name : ''"
Anju
Auteur

Je ne comprends pas ce que tu veux dire... Chaque droit a forcément un profil et une application puisque c'est la clé primaire :/

Je suis en train de me dire que j'ai peut-être mal géré ma table Droits en fait...

Oui je pense, tu devrais faire une table Droits avec une clé primaire id, et clés étrangères profil_id & application_id et d'autres champs pour régler les droits correspondant au Profil et Application concerné.

tu peut voir du coté de hasAndBelongsToMany tes clés des tables Profil et application migrent dans droit la tu aura les résultats exacts