1
votes

I cant save (update) associated form data for model AvailabilityForTutors that has a hasMany relationship with the Primary model. I used checkboxes to update some options for the 'AvailabilityForTutors. not_available' field. I added in id's but that made no difference. The updated 'AvailabilityForTutors. not_available' field is not being updated in the database. I dont get an error and the primary model data for the Tutor does save.

I checked the docs and past posts for this straightforward task and I cant get it. I am doing something wrong.

//controller
  $tutor = $this->Tutors->get($id, [
        'contain' => ['AvailabilityForTutors']
    ]);
  if ($this->request->is(['patch', 'post', 'put'])) {


         debug($this->request->data);
            $tutor = $this->Tutors->patchEntity($tutor, $this->request->data,['associated' => ['AvailabilityForTutors'],'validate' => false ] );

            if ($this->Tutors->save($tutor)) {
                $this->Flash->success(__('The tutor has been saved.'));
               return $this->redirect(['action' => 'edittest2',$id]);
            } else {
                $this->Flash->error(__('The tutor could not be saved. Please, try again.'));
            }


        }

//view

  <?php

            echo $this->Form->hidden('id', ['value'=>$id]);
            echo $this->Form->input('first_name',['label' => 'Tutor FirstName']);
            echo $this->Form->input('last_name',['label' => 'Tutor LastName']);




            foreach ($tutor->availability_for_tutors as $key => $item) {

               echo $this->Form->hidden('AvailabilityForTutors.'.$key.'.id', ['value'=>$item->id]);

               echo $this->Form->input('AvailabilityForTutors.'.$key.'.not_available', ['label'=>$item->weekday,
                'checked'=> $item->not_available,'type'=>'checkbox']);



           }


model tutor//

 $this->hasMany('AvailabilityForTutors', [
            'foreignKey' => 'tutor_id'
        ]);


posted data which is correct


'id' => '12',
    'first_name' => 'fred',
    'last_name' => 'Tow',
    'AvailabilityForTutors' => [
        (int) 0 => [
            'id' => '36',
            'not_available' => '1'
        ],
        (int) 1 => [
            'id' => '37',
            'not_available' => '0'
        ],
        (int) 2 => [
            'id' => '38',
            'not_available' => '0'
        ],
http://stackoverflow.com/questions/27398100/cakephp-3-0-cant-save-hasmany-associated-data
http://book.cakephp.org/3.0/en/orm/saving-data.html#saving-with-associations

http://stackoverflow.com/questions/35018335/update-a-hasmany-records

UPDATE- debug patched data object(App\Model\Entity\Tutor) {

'id' => (int) 12,
'tutor_inactive' => false,
'first_name' => 'fred2',
'last_name' => 'Tow2',

'availability_for_tutors' => [
    (int) 0 => object(App\Model\Entity\AvailabilityForTutor) {

        'id' => (int) 36,
        'not_available' => false,
        ....
],
'AvailabilityForTutors' => [
    (int) 0 => [
        'id' => '36',
        'not_available' => '1'

//see not_available is different from patched data output

3
Does your entity look right after you patch it? What's the name and schema of the table where these availability records should be saved? Are 36, 37 and 38 the IDs of Tutors? - Greg Schmidt
The patched data from the debug has the the old AvailabilityForTutors values and then this table appears again with the new values with the id correct field (see update in OP). I really need this done can I please get an example. I see a lot of people have trouble with this - ajt
I also tried saving with $this->Tutors->save($tutor,[ 'atomic'=>false, 'validate' => false, 'associated' => ['AvailabilityForTutors'] it has not saved the associated data - ajt
The fact that there are two arrays with different names in your patched entity is why it's not saving. Note that the entity name on the data that was read is AvailabilityForTutor (singular). Your new data has a plural key. Try using the singular in your form? Also, you've only answered one of my three questions... - Greg Schmidt
yes that worked if the lower case in the view availability_for_tutors. Now I have 2 solutions . Well you thought of the first. I put 2 solutions up - ajt

3 Answers

0
votes

maybe one of these methods will help you i guess you need replace http://api.cakephp.org/3.2/class-Cake.ORM.Association.HasMany.html

I tried it the same way as you and failed but with link() it worked for me (for HABTM)

0
votes

Try inserting $tutor->dirty('availability_for_tutors', true); inside the Controller, after the patchEntity function. It will mark your association as 'dirty'(modified) so that it can save it when $this->Tutors->save method is called.

0
votes
         I have 2 solutions
1st

  public function edittest2($id = null)
    {
        $tutor = $this->Tutors->get($id, [
            'contain' => ['AvailabilityForTutors']
        ]);
        if ($this->request->is(['patch', 'post', 'put'])) {


       //  debug($this->request->data);
            $tutor = $this->Tutors->patchEntity($tutor, $this->request->data(),['associated' => ['AvailabilityForTutors']] );
         //    $tutor->dirty('availability_for_tutors', true);

        //  debug($tutor);
             $this->Tutors->save($tutor,[
                        'atomic'=>false,
                        'validate' => false,
                        'associated' => ['AvailabilityForTutors']
                    ]); 


             return $this->redirect(['action' => 'edittest2',$id]);
        }



 view

 foreach ($tutor->availability_for_tutors as $key => $item) {

               echo $this->Form->hidden('availability_for_tutors.'.$key.'.id', ['value'=>$item->id]);

                echo $this->Form->input('availability_for_tutors.'.$key.'.not_available', ['label'=>$item->weekday,
                    'checked'=> $item->not_available,'type'=>'checkbox']);


           }


      2nd 
         public function edittest4($id = null)
            $tutor = $this->Tutors->get($id, [
                'contain' => ['AvailabilityForTutors']
            ]);


            $availability=$tutor['availability_for_tutors'];


            if ($this->request->is(['patch', 'post', 'put'])) {


                $tutor = $this->Tutors->patchEntity($tutor, $this->request->data(),['validate' => false ] );

                 $this->Tutors->save($tutor); 

                 $newavailability = $this->Tutors->AvailabilityForTutors->patchEntities(  $availability,$tutor->AvailabilityForTutors, ['validate' =>  false]); //multiple entities
                foreach ($newavailability as $key => $item) {
                   $result=$this->Tutors->AvailabilityForTutors->save($item, ['checkExisting' => false]);

                    if ( $result ){
                       $this->Flash->success(__('A lesson has been saved on .'));

                    }
                    else{
                      $this->Flash->error(__('There has been an error saving a lesson. Please, try again.'));
                    }//if

                 }//for each



                 return $this->redirect(['action' => 'edittest4',$id]);
            }


    view
    ///
     foreach ($availability as $key => $item) {
                 //  debug($item->toArray());
                echo $this->Form->hidden('AvailabilityForTutors.'.$key.'.id', ['value'=>$item->id]);

                      echo $this->Form->input('AvailabilityForTutors.'.$key.'.not_available', ['label'=>$item->weekday,
                        'checked'=> $item->not_available,'type'=>'checkbox']);


               }