Bonjour à tous,
Je suis en train d'essayer d'apprendre a utiliser cakephp.
Pour cela j'essaye de "migrer" un début d'appli que j'avais commencé en php classique vers cakephp.

Je me pose une question sur comment inserer des données dans plusieurs tables en une seule "action". (clique sur un bouton).
Mon programme est un carnet de musculation. Pour ajouter une séance voici comment je procède:
Mon controleur:

    if(isset($_POST)){
      var_dump($_POST);
      echo '------------</br>';

      $m = new Seance(['commentaire'=>'Nouvelle seance', 'dateSeance'=>'2015-12-18']);

      foreach($_POST as $s){
        $e = new Exercice(['idExercice'=>$s['id']]);
        for($i=0;$i<$taille;$i++){
          echo $s['rep'][$i].'x'.$s['charge'][$i] .'</br>';
          $rep = $s['rep'][$i] ; $charge = $s['charge'][$i] ;
          $serie = new Serie(['nbRep'=>$rep, 'charge'=>$charge ]);
          $e->ajoutSerie($serie);
        }

        $m->ajoutExercice($e);
        echo '-----------</br>';
      }

      $manager->add($m);

    }

Et mon manager:
public function add(Seance $seance){

    // Requete d'insertion d'une nouvelle séance
    $q = $this->_db->prepare('INSERT INTO seance SET
        commentaire = :com, idUser = :idUser, idSport = :idSport, dateSeance = :date_s;');

    $q ->bindValue(':com' , $seance->getCommentaire());
    $q ->bindValue(':idUser', 1, PDO::PARAM_INT);
    $q ->bindValue(':idSport', 1,PDO::PARAM_INT);
    $q ->bindValue(':date_s', $seance->getDateSeance());

    $q->execute();

    $exos= $seance->getListExercice(); // On récupère la liste des exos qui composent la séance
    foreach($exos as $exo){
      var_dump($exo);
      $lesSeries = $exo->getList();// Pour chaque exercice, on récupere dans lesSeries, la liste des séries de l'exercice
      $q = $this->_db->prepare('INSERT INTO composer SET
              idSeance = :idSeance, idExercice = :idExercice');
      $q -> bindValue(':idSeance', $idSeance, PDO::PARAM_INT);
      $q -> bindValue(':idExercice', $exo->getIdExercice(), PDO::PARAM_INT);
      $q -> execute();
      foreach($lesSeries as $serie){
        // Requete d'insertion de chaque série
        $q = $this->_db->prepare('INSERT INTO serie SET nbRep = :nbRep, charge = :charge, idSeance = :idSeance, idExercice = :idExercice');
        $q->bindValue(':nbRep', $serie->getNbrep(), PDO::PARAM_INT);
        $q->bindValue(':charge', $serie->getCharge(), PDO::PARAM_INT);
        $q->bindValue(':idSeance', $idSeance, PDO::PARAM_INT);
        $q->bindValue(':idExercice', $exo->getIdExercice(), PDO::PARAM_INT);

        $q->execute();
      }
    }
  }

Donc en gros, j'ai mes classes seance, exercice et serie qui sont construite lors de la validation d'un formulaire. Puis mon manager décompose pour insérer dans les bonnes tables les bonnes données.

Comment procéder avec cakephp pour avoir ce genre de comportement ?
J'espere ne pas etre confus si non ne pas hésité a demander des infos.

Merci

11 réponses


Avant tout tu utilises cake 2 ou cake 3 ?
Si j'ai bien compris seance hasMany exercices et exercice hasMany series ? C'est ca ?

alex8276
Auteur

Bonjour,
merci pour ton retour,
Je me suis mis au 3.
Ouic'est bien ça

On commence par ajouter les relations nécéssaires(lier les model)

// /Model/Table/SeancesTable.php

public function initialize(){
    $this->hasMany('Exercices');
}

// /Model/Table/ExecricesTable.php
public function initialize(){
    $this->hasMany('Series');
}

Le tableau(array) des données à insérer doit avoir cette structure:

$requestData = [
    'Seances' => [
        'commentaire' => 'seance matinale',
        'autre_champs' => '...',
        'exercices' => [
            [
                'titre' => 'execrice 1',
                'autre_champs' => '...',
                'series' => [
                    ['type' => 'serie de 12', 'autre_champs' => '...'],
                    ['type' => 'serie de 10', 'autre_champs' => '...']
                ]
            ],
            [
                'titre' => 'execrice 2',
                'autre_champs' => '...',
                'series' => [
                    ['type' => 'serie de 13', 'autre_champs' => '...'],
                    ['type' => 'serie de 11', 'autre_champs' => '...']
                ]
            ]
        ]
    ]
];

Maintenant on convertie le tableau en entity et on passe à la sauvegarde

$seance = $this->Seances->newEntity($requestData);
$this->Seances->save($seance);

Cakephp va faire le reste et il injecte automatiquement toutes les clés étrangères(seance_id dans excercies et execrice_id dans series)

alex8276
Auteur

Merci je vais tester ça. Ca m'a l''air magique tout ça lol

alex8276
Auteur

Bonjour,
J'ai pu me replonger ce soir dans mon test de projet. Et je bloque encore malgré les explications précédente.
Première question: Est ce que je dois créer un modèles pour Series ou est ce que la fonction au dessus peut s'en passer ?
En suite j'ai une table de jointure , même question dois je créer un model ?
Donc on a une seance qui est composé de un ou plusieurs exercices
seance composé de une ou plusieurs séries
Serie est dans une seule seance et un seul exercice
un Exercice peut etre dans plusieurs seance

http://hpics.li/f68cb90

Le premier test que j'ai fais m'insère que la séance

$requestData = [
            'Seances' =>[
                'commentaire' => 'test cake 3',
                'date_seance' => '2016-02-27',
                'user_id' => 1,
                'exercices_seances'=> [
                    [
                        'exercice_id'=>1,
                        'seance_id'=>28
                    ]
                ],
                'series' => [
                    [
                        'nb_rep' => 17,
                        'charge' => 520
                    ]
                ]
            ]
        ];

De plus ca m'insere une date totalement improbable : 1922-09-19. Pour mon test $requestData est dans le controller seance, est ce la bonne place ?
merci

alex8276
Auteur

Bon j'ai créé mon modèle série, mais je comprend pas trop ce les liaisons qu'il m'a fais!

 $this->belongsTo('Seances', [
            'foreignKey' => 'seance_id'
        ]);
        $this->belongsTo('Exercices', [
            'foreignKey' => 'exercice_id'
        ]);

Cela veux dire que serie est relié a seance et exercice par les clé etrangère ? Dans ce cas dois je créer un modèle avec ma table de liaison exercices_seances ou est ce géré par le code au dessus?

alex8276
Auteur

Alors la je seche completement, l'insertion de mes données fonctionne qu'a moitié.
voici ce que j'ai

class SeancesTable extends Table
{
    public function initialize(array $config)
    {
        //$this->hasMany('Exercices');
        $this->hasMany('Series');
        $this->belongsToMany('Exercices');
        $this->addBehavior('TimesTamp');
    }
}

class SeriesTable extends Table
{
    public function initialize(array $config)
    {
        parent::initialize($config);

        $this->table('series');
        $this->displayField('id');
        $this->primaryKey('id');

        $this->belongsTo('Seances');
        //$this->hasOne('Seances');

    }

    public function add(){

        $requestData = [
            'Seances' =>[
                'commentaire' => 'test cake 33',
                'date_seance' => '2016-02-27',
                'user_id' => 1,
                'Series' => [
                    ['nb_rep' => 17, 'charge' => 520, 'exercice_id'=>1],
                    ['nb_rep' => 27, 'charge' => 600]
                ]
            ]
        ];

        $seance = $this->Seances->newEntity($requestData,[
            'associated' => ['Series']
        ]);
       $this->Seances->save($seance);
    }

Je n'ai que la table séance qui se rempli. Pas celle des séries et aucune erreur n'est retourné !
Une idée ?
Merci d'avance

Bonjour.
La fonction add, tu dois la mettre dans le controller et non dans le model.

alex8276
Auteur

Bonjour Lartak,
C'étais bien le cas (Copier coller un peu rapide c'est pour ça que ca n apparait pas ici)
J'ai résolu mon problème mais pas comme c'est dans la doc. Si tu as une explication voila ce que j'ai et qui marche.

class SeancesController extends AppController
{
    public function add(){
        $requestData = [
        'Seance'=>[
            'commentaire'=>"test encore",
            'date_seance' => '2016-03-12',
            'user_id' => 1,
            'series' => [
                [
                'nb_rep'=>18,
                'charge' => 219
                ]
            ]
        ]

        ];

        $seance = $this->Seances->newEntities($requestData);
        debug($seance);
        foreach ($seance as $e) {
            $this->Seances->save($e);
        }

Alors que d'après la doc je devrais juste faire. Mais dans ce cas ca ne m'insert pas les données de ma table Series

$seance = $this->Seances->newEntity($requestData);
$this->Seances->save($seance);

Autre question, est ce que tu sais pourquoi ma date '2016-03-12' est enregistré en BD => 1907-09-20 ??

Autre question, est ce que tu sais pourquoi ma date '2016-03-12' est enregistré en BD => 1907-09-20 ??

Quel est le format du champ date_seance dans ta table, date ou datetime ?

alex8276
Auteur

c'est date le format. Faut passer en datetime du coup ?