Bonjour,
J'utilise CakePHP 3.
Pour commencer, voici ma table Profils (je me suis dis que des images seraient plus parlantes que du blabla ^^ ) :
Ensuite, voici mon tableau sur mon site :
Voici ma fonction edit() de mon controller ProfilsController :
public function edit($id = null)
{
$profil = $this->Profils->get($id, [
'contain' => []
]);
if ($this->request->is(['patch', 'post', 'put'])) {
$profil = $this->Profils->patchEntity($profil, $this->request->data);
if ($this->Profils->save($profil)) {
$this->Flash->success(__('Le profil a bien été modifié.'));
return $this->redirect(['action' => 'index']);
} else {
$this->Flash->error(__('Le profil n\'a pas été modifié. Veuillez réessayer.'));
}
}
$this->set(compact('profil'));
$this->set('_serialize', ['profil']);
}
Et mon tableau HTML :
<table cellpadding="0" cellspacing="0">
<thead>
<tr>
<th class="actions">
<button class="widget-update"><?php echo $this->html->image('update.gif') ?></button>
<button class="widget-back planqueW"><?php echo $this->html->image('back.gif') ?></button>
<?= $this->Form->create($profils, ['url' => ['controller' => 'profils', 'action' => 'edit']]) ?>
<button class="widget-save planqueW" type="submit"><?php echo $this->html->image('save.gif') ?></button>
</th>
<th>DP</th>
<th>CP</th>
<th>Référent</th>
<th>Sachant</th>
<th>Intervenant</th>
<th>MOE</th>
</tr>
</thead>
<tbody>
<?php $i = 0;
$j = 10; ?>
<tr id="news">
<th>News</th>
<?php foreach ($profils as $profil): ?>
<?php if($i>0) { ?>
<td id="<?= $i ?>">
<span class="cellTexteW"><?= h($profil->role_news); ?></span>
<?= $this->Form->input('role_news', ['label' => false, 'class' => 'planqueW champSaisiW', 'default' => $profil->role_news, 'options' => ['aucun accès' => 'Aucun accès', 'consultatif' => 'Consultatif', 'contributeur' => 'Contributeur', 'administrateur' => 'Administrateur']]); ?>
</td>
<?php } ?>
<?php $i++; ?>
<?php endforeach; ?>
</tr>
<tr id="agenda">
<th>Agenda</th>
<?php foreach ($profils as $profil): ?>
<?php if($j>10) { ?>
<td id="<?= $j ?>">
<span class="cellTexteW"><?= h($profil->role_calendar); ?></span>
<?= $this->Form->input('role_calendar', ['label' => false, 'class' => 'planqueW champSaisiW', 'default' => $profil->role_calendar, 'options' => ['aucun accès' => 'Aucun accès', 'consultatif' => 'Consultatif', 'contributeur' => 'Contributeur', 'administrateur' => 'Administrateur']]); ?>
</td>
<?php } ?>
<?php $j++; ?>
<?php endforeach; ?>
</tr>
<?= $this->Form->end() ?>
</tbody>
</table>
Maintenant, voici mon problème :
Lorsque l'on clique sur le bouton update dans mon tableau (sur le site), tous mes champs deviennent des select où l'on peut choisir le rôle que l'on veut. Toutefois, c'est une modification sur plusieurs enregistrements de la table en même temps, on ne choisit pas d'enregistrement spécifique.
Ma colonne DP correspond à mon enregistrement 2, CP au 3, etc. Mais ils sont modifiables tous en même temps.
Je sais que ma fonction edit() est fausse car elle demande un id spécifique.
Mais je ne vois pas comment la modifier pour que tous mes enregistrements soient modifiables en même temps :/
Pourriez-vous m'aider s'il vous plait ? J'avoue que je bloque totalement, et je dois absolument terminer cette fonction pour vendredi :(
Merci par avance !
Yop. Il faut faire en sorte que les données retournées par ton formulaire $this->request->data()
aient ce format-ci:
Dans ta méthode edit
il faut:
newEntity($data)
foreach
et utiliser les méthodes dédiées aux sauvegardes des données (patchEntity($entity, $data)
,save($patchEntity)
) dans le foreach
.Aussi pour que cela puisse fonctionner, il faut que ton Entité Profil accepte que les assignements en masse puisse s'executer sur l'ID. Pour cela soit:
'id'
et le mettre à true
. (Normalement à false
si le code est généré par CakePHP via la cosnole)newEntity($data, $options)
la clé 'accessibleFields'
avec la liste des champs à assigner en masse, ici: ['id' => true]
.J'ai ceci comme methode edit
.
public function edit()
{
if ($this->request->is(['patch', 'post', 'put'])) {
$entities = $this->Profils->newEntities($this->request->data(), [
'accessibleFields' => ['id' => true],
]);
foreach ($entities as $entity) {
$profil = $this->Profils->patchEntity($entity, $this->request->data());
$this->Profils->save($profil);
}
return $this->redirect(['action' => 'index']);
}
}
oki, et bien je ne saurais pas t'aider, je suis sous CakePHP 2 et ma fonction edit ne ressemble en rien à la tienne, je suis désolé :( mais je devrais bientôt m'y attaquer !
Tu dis que tous les champs deviennent des select, et juste après tu dis qu'on ne choisit pas de champs spécifique. J'ai pas compris la problématique dsl.
Et bien, tous les champs du tableau du site deviennent des selects. En même temps.
Mais chaque select correspond à un champ de la table et d'un enregistrement. Par exemple, sur l'image de mon tableau du site, le "administrateur" entre DP et News, correspond à l'enregistrement 2 et au champ role_news. Alors que le "administrateur" entre CP et Agenda correspond à l'enregistrement 3 et au champs role_calendar. Donc ça touche plusieurs champs de plusieurs enregistrements en même temps. Et ils doivent être modifiables en même temps.
J'espère que je me suis mieux expliquée :/
Bonjour PhiSyX ! Merci pour ta réponse :)
J'ai commencé une nouvelle fonction edit(), après avoir mis l'id à true dans le $_accessible :
public function edit($id = null)
{
if($this->request->is(['patch', 'post', 'put']))
{
$data = $this->request->data;
$profil = $this->Profils->newEntity($data);
debug($profil);
foreach($profil as $p)
{
$p = $this->Profils->patchEntity($profil, $data);
debug($p);
$this->Profils->save($p);
}
}
}
Pour le moment, ça me renvoie ceci :
object(App\Model\Entity\Profil) {
'role_news' => 'aucun accès',
'role_calendar' => 'aucun accès',
'[new]' => true,
'[accessible]' => [
'*' => true,
'id' => true
],
'[dirty]' => [
'role_news' => true,
'role_calendar' => true
],
'[original]' => [],
'[virtual]' => [],
'[errors]' => [
'name' => [
'_required' => 'This field is required'
]
],
'[repository]' => 'Profils'
}
Ce qui correspond à la 7ème colonne, je sais pas trop pourquoi d'ailleurs... Mais il n'entre pas dans le foreach en tout cas :/
Je ne savais pas trop s'il fallait que je mette un if($this->request->is(['patch', 'post', 'put'])), mais que je le mette ou non, ça ne change rien, ça renvoie la même chose.
Mais est-ce que tu peux me dire si je suis bien partie ? :) Et m'aider en ce qui concerne le foreach, pourquoi n'entre-t-il pas dedans ? Et je ne vois pas comment donner le format dont tu as parlé au $this->request->data :/
Encore merci pour ton aide !
P.S : Je suis tombée là dessus aussi : http://book.cakephp.org/3.0/fr/orm/saving-data.html Tu penses que ça pourrait servir ?
Yop.
Ha oui. Il faut désactiver la validation (qui est faites par défaut avec newEntity (et patchEntity)).
On le voit d'ailleurs:
'[errors]' => [
'name' => [
'_required' => 'This field is required'
]
]
Et oui le lien peut te servir, surtout la partie "Convertir des Enregistrements Multiples" dans ce cas-ci. (Ce que j'ai expliqué, en gros.)
Pour les données, il y a plusieurs façon de faire, la plus simple est de passer à l'helper $this->Form->input("{$keyProfil}.role_{$keyField}")
.
N'oublie pas d'ajouter un input type hidden "{$keyProfil}.id"
à ta vue (pour que la sauvegarde se fasse de manière "mise à jour" et non d'un ajout à de nouvelles entités) ^^
$keyProfil
correspond à la clé foreach ($profils as $keyProfil => $profil)
dans ta vue. (a été ajoutée par moi même ^^)
Chez toi $keyField
n'existe pas parce que tu l'as fait manuellement mais c'est égal à 'news' et/ou 'calendar'.
J'ai enlevé la validation ! Mais par contre, il entre toujours pas dans le foreach.
Pour le reste je suis désolée, mais je ne comprends pas ce que tu veux dire :s
{$keyProfil}.role_{$keyField} c'est pas du jquery ça ? Je comprends pas la syntaxe, désolée :/
Ok, non ça n'est pas du jQuery.
La syntaxe est celle de PHP, lorsque l'on met une {$variable} ou tout simplement $variable au sein d'une chaîne de caractère avec double guillemets, la variable sera interprétée. (Mais c'est la base des bases ^^)
$foo = 'bar';
echo "Je suis $foo"; // Je suis bar
echo "Je suis {$foo}"; // Je suis bar
echo 'Je suis $foo'; // Je suis $foo
Quand on sait ça, on peut comprendre ce que veut dire "{$keyProfil}.role_{$keyField}"
.
"{$keyProfil}.role_{$keyField}"
sera transformé en "0.role_news"
,"1.role_news"
/"0.role_calendar"
,"1.role_calendar"
, etc...
De cette manière on défini l'envoi de plusieurs données, en tableau.
$keyProfil
correspond à un index (celui généré automatiquement par le foreach
par exemple)..
notation avec points définit un chemin de tableau. ( En savoir plus: http://book.cakephp.org/3.0/fr/appendices/glossary.html#term-notation-avec-points )role_{$keyField}
correspond a ton champ en bdd. J'ai mis $keyField
mais il faut que tu mettes news
et calendar
manuellement.En bref, le code généré par l'helper form donnera ceci: <select name"0[role_news]">...</select>
/<select name"0[role_calendar]">...</select>
, etc... .
Lors de l'envoi du formulaire les données te seront retournées comme telles: $this->request->data
[
0 => [
'id' => 1,
'role_news' => 'sans aucun accès',
'role_calendar' => 'sans aucun accès',
],
1 => [
'id' => 2,
'role_news' => 'admin',
'role_calendar' => 'contrib',
],
];
Aaaah d'accord ! Je crois que je comprends mieux ! C'est parce que j'utilise jamais cette syntaxe en fait ^^
Je vais essayer de faire ça !
Si j'ai bien compris :
Par contre, désolée si je t'embête hein ^^', mais à quel moment le $keyProfil prend la valeur de l'id ?
Edit : Cette dernière question étant stupide, puisque tu y as déjà répondu, oublie la xD je vais essayer tout ça !
Edit 2 :
j'ai réussi :D
Ca me renvoie ceci :
[
(int) 1 => [
'id' => '2',
'role_news' => 'administrateur',
'role_calendar' => 'administrateur'
],
(int) 2 => [
'id' => '3',
'role_news' => 'administrateur',
'role_calendar' => 'administrateur'
],
(int) 3 => [
'id' => '4',
'role_news' => 'contributeur',
'role_calendar' => 'contributeur'
],
(int) 4 => [
'id' => '5',
'role_news' => 'contributeur',
'role_calendar' => 'contributeur'
],
(int) 5 => [
'id' => '6',
'role_news' => 'consultatif',
'role_calendar' => 'contributeur'
],
(int) 6 => [
'id' => '7',
'role_news' => 'aucun accès',
'role_calendar' => 'aucun accès'
]
]
Maintenant faut que je passe à l'enregistrement des modifications :o
Parce qu'il ne rentre toujours pas dans mon foreach :(
Ca fonctiooooonne :D
Merci beaucoup, vraiment :D
Juste une question, si j'ai mis id => true dans mon entité Profil, est-ce que c'est vraiment utile de le remettre dans la fonction ? :o
Coooool! Non, ça n'est pas utile ^^
Par contre tu peux améliorer ton index.ctp niveau repetition (Et formulaire \ö/)
<?= $this->Form->create(null, ['id' => 'profil-form', 'url' => ['controller' => 'profils', 'action' => 'edit']]) ?>
<?= $this->Form->end() ?>
<table cellpadding="0" cellspacing="0">
<thead>
<tr>
<th class="actions">
<button class="widget-update"><?php echo $this->html->image('update.gif') ?></button>
<button class="widget-back planqueW"><?php echo $this->html->image('back.gif') ?></button>
<button class="widget-save planqueW" type="submit" form="profil-form"><?php echo $this->html->image('save.gif') ?></button>
</th>
<th>DP</th>
<th>CP</th>
<th>Référent</th>
<th>Sachant</th>
<th>Intervenant</th>
<th>MOE</th>
</tr>
</thead>
<tbody>
<?php $fields = ['news' => 'News', 'calendar' => 'Agenda'] ?>
<?php foreach ($fields as $keyField => $field): ?>
<tr id="<?= $keyField ?>">
<th><?= $field ?></th>
<?php foreach ($profils as $keyProfil => $profil): ?>
<td>
<span class="cellTexteW"><?= h($profil->{'role_' . $keyField}) ?></span>
<?= $this->Form->input("{$keyProfil}.id", [
'form' => 'profil-form',
'id' => false,
'type' => 'hidden',
'value' => $profil->id,
]) ?>
<?= $this->Form->input("{$keyProfil}.role_{$keyField}", [
'form' => 'profil-form',
'id' => false,
'label' => false,
'class' => 'planqueW champSaisiW',
'default' => $profil->{'role_' . $keyField},
'options' => [
'aucun accès' => 'Aucun accès',
'consultatif' => 'Consultatif',
'contributeur' => 'Contributeur',
'administrateur' => 'Administrateur'
]
]) ?>
</td>
<?php endforeach ?>
</tr>
<?php endforeach ?>
</tbody>
</table>
Oh je vais essayer ça, merci :)
Mais si mon bouton submit ne se trouve pas dans le formulaire, ça va pas envoyer la réponse, non ?
Du coup, j'ai testé, ça fonctionne bien !
Petit problème pourtant, tu as enlevé mes variables $i et $j :/
En effet, en fait dans ma table Profils, j'ai 7 profils ! Mais moi je n'en affiche que 6.
Mes variables $i et $j permettent de ne pas afficher le <td id=0> et <td id=10> qui représente donc le premier enregistrement de ma table Profils :/
Du coup, j'ai juste rajouté un if dans ton code, et c'est parfait \o/