2017-08-29 4 views
1

J'ai appris here comment on peut sauvegarder les données dans les champs de la table de jointure CoursesMemberships en ajoutant ou éditant un student dans CakePHP 3.x. Pour ajouter grades pour beaucoup courses Je peux le faire dans mes add et edit formes:Enregistrement des données dans la table de jointure à l'aide des options de contrôle dans CakePHP 3.x

echo $this->Form->control('courses.0.id', ['type' => 'select', 'options' => $courses]); 
echo $this->Form->control('courses.0._joinData.grade'); 

echo $this->Form->control('courses.1.id', ['type' => 'select', 'options' => $courses]); 
echo $this->Form->control('courses.1._joinData.grade'); 

echo $this->Form->control('courses.2.id', ['type' => 'select', 'options' => $courses]); 
echo $this->Form->control('courses.2._joinData.grade'); 
... 

mais cette forme:

  1. a un nombre fixe de courses pour chaque student;
  2. nécessite de sélectionner le course id dans la liste ('type' => 'select');
  3. ajoute tous les cours au dossier de l'étudiant même s'il n'est pas assisté (bien, le champ grade correspondant peut être gardé vide, mais quand même).

Est-il possible d'avoir une forme plus simple, où tous courses sont répertoriés et on ne peut la case à cocher course assisté et entrez le grade correspondant? Je l'ai trouvé très difficile en utilisant control ...

EDIT: Après @ndm suggéré une méthode très bien ci-dessous, j'ai mis dans le add.ctp:

foreach ($courses as $key => $course) { 

echo $this->Form->control('courses.'.$key.'.id', ['type' => 'checkbox', 'hiddenField' => false, 'value' => $key, 
    'label' => $key]); 
echo $this->Form->control('courses.'.$key.'._joinData.grades'); 
} 

et corrigeais StudentsTable.php en conséquence. Et cela fonctionne sans problèmes.

Cependant, si je fais la même chose dans edit.ctp, les enregistrements précédemment enregistrés (par exemple, pour 1, 3, 5 et 7 courses sont maintenant répertoriés comme 1, 2 et 3 montrant la grades pour l'ancien 3 5 et 7 courses et la Je comprends que le premier enregistrement a disparu parce que mon courses commence par id=1 (tout comme la clé $ dans la boucle) et «courses.0.id» est manquant, mais le problème général est que les champs vides supprimés par la fonction beforeMarshal ne sont plus reconnus sous la forme edit.ctp et que je ne trouve pas un moyen raisonnable d'éditer l'enregistrement student's

Répondre

0

Il n'y a pas de construction à l'appui de ce que vous essayez d'accomplir, vous devrez trouver une solution personnalisée, qui exigera probablement un mélange de forme et de logique de triage, ou de JavaScript.

Vous pouvez créer par exemple une liste de cases à cocher et utilisez la valeur id (Wich sera nul dans le cas où la case est décochée, ou l'ID dans le cas où il est vérifié) pour supprimer les entrées non contrôlées de la les données soumises avant de triage, quelque chose comme ceci:

echo $this->Form->control('courses.0.id', [ 
    'type' => 'checkbox', 
    'value' => $courses[0]->id, 
    'label' => $courses[0]->title 
]); 
echo $this->Form->control('courses.0._joinData.grade'); 

echo $this->Form->control('courses.1.id', [ 
    'type' => 'checkbox', 
    'value' => $courses[1]->id, 
    'label' => $courses[1]->title 
]); 
echo $this->Form->control('courses.1._joinData.grade'); 

// ... 
// in the `StudentsTable` class 

public function beforeMarshal(\Cake\Event\Event $event, \ArrayObject $data, \ArrayObject $options) 
{ 
    forach ($data['courses'] as $key => $course) { 
     if (empty($course['id'])) { 
      unset($data['courses'][$key]) 
     } 
    } 
} 

Sinon, vous pouvez utiliser JavaScript pour désactiver les contrôles relatifs à la case à cocher afin qu'ils ne sont pas soumis en premier lieu. Pour que cela fonctionne correctement, vous devez vous assurer que vous désactivez le champ caché généré par défaut pour les cases à cocher (voir l'option hiddenField), sinon zéro sera envoyé pour les cases à cocher non cochées.

Voici un exemple jQuery rapide, non testé pour illustrer le principe:

echo $this->Form->control('courses.0.id', [ 
    'class' => 'course-checkbox', 
    'data-join-data-input' => '#course-join-data-0', 
    'type' => 'checkbox', 
    'hiddenField' => false, // no fallback, unchecked boxes aren't being submitted 
    'value' => $courses[0]->id, 
    'label' => $courses[0]->title 
]); 
echo $this->Form->control('courses.0._joinData.grade', [ 
    'id' => 'course-join-data-0', 
    'disabled' => true 
]); 

// ... 
$('.course-checkbox').each(function() { 
    var $checkbox = $(this); 
    var $joinDataInput = $($checkbox.data('join-data-input')); 

    $checkbox.on('change', function() { 
     $joinDataInput.prop('disabled', !$checkbox.prop('checked')); 
    }); 
}); 

Voir aussi

+0

Je suis très reconnaissant pour les solutions élégantes et une explication détaillée! J'ai commencé à implémenter le premier et j'ai reçu ce message d'erreur: Impossible d'utiliser l'objet de type Cake \ ORM \ Query en tant que tableau (ligne 'value' => $ courses [0] -> id,) –

+0

Vous devriez le convertir à un tableau utilisant d'abord '$ courses-> toArray()', et '$ courses' aurait besoin d'être une requête régulière (pas une liste). J'ai supposé que vous voulez générer un nombre spécifique de cours en fonction de votre extrait d'exemple. Alternativement, vous pouvez itérer sur '$ courses' et utiliser key/value au lieu d'accéder aux propriétés dans le cas où' $ courses' est une requête de recherche de liste. – ndm

+0

Incroyable! Tout fonctionne comme vous l'avez expliqué. Comme toujours. Merci beaucoup! –