Saving related models in Cakephp 3

I have a form that collects data about an article, and I want to save this data, as well as for a model called Abstract, where the article hasMany Abstracts. My models look like this:

namespace App\Model\Table; use Cake\ORM\Table; use Cake\Validation\Validator; class AbstractsTable extends Table { public function initialize(array $config) { $this->belongsTo('Articles'); } public function validationDefault(Validator $validator) { $validator ->notEmpty('body'); return $validator; } } 

AND

 namespace App\Model\Table; use Cake\ORM\Table; use Cake\Validation\Validator; class ArticlesTable extends Table { public function initialize(array $config) { $this->addBehavior('Timestamp'); $this->hasMany('Abstracts'); } public function validationDefault(Validator $validator) { $validator ->notEmpty('category') return $validator; } } 

In my input form there is a field called "abstracts.body", and in my ArticlesController I have this function:

  public function add() { $data = $this->request->data; $article = $this->Articles->newEntity($data, [ 'associated' => ['Abstracts'] ]); if ($this->request->is('post')) { $article->user_id = $this->Auth->user('id'); $data['abstracts']['user_id'] = $article->user_id; $data['abstracts']['approved'] = 0; $article = $this->Articles->patchEntity($article, $data, [ 'associated' => ['Abstracts'] ]); if ($this->Articles->save($article, [ 'validate' => false, 'associated' => ['Abstracts'] ]) ) { $this->Flash->success(__('Your article has been saved.')); return $this->redirect(['action' => 'index']); } $this->Flash->error(__('Unable to add your article.')); } $this->set('article', $article); } 

My Abstracts table is pretty simple:

 CREATE TABLE 'abstracts' ('id' INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, 'article_id' INTEGER , 'user_id' INTEGER , 'body' TEXT, 'approved' BOOLEAN ) 

From debugging, I see that I have the correct array of abstracts in my $ data (in add ()), but it seems to never try to save it to the database. Can someone point out my mistake? Thanks!

+6
source share
2 answers

Got it.

I started to make mistakes here:

 My input form has a field named 'abstracts.body' 

Since this is a hasMany relationship, I need this input to be 'abstracts.0.body'

Then the rest of LeWestopher's answer will work - adding an index to the fields that I want to populate from the controller, so $ data [abstracts] [0] ['user_id'] => ... and so on, Thanks!

+4
source

You are processing the $ data ['abstracts'] array incorrectly, as a result of which the association is not saved. $ Data ['abstracts'] is expected to be an array of abstracts. Your problem is here:

 $data['abstracts']['user_id'] = $article->user_id; $data['abstracts']['approved'] = 0; 

You can easily fix this by changing this to:

 foreach($data['abstracts'] as $index => $abstract) { $abstract['user_id'] = $article->user_id; $abstract['approved'] = 0; $data['abstracts'][$index] = $abstract; } 

This should correctly iterate over the array of abstract arrays, set user_id and the approved keys correctly, and then store it correctly.

CakePHP 3.x Association Conservation Documentation

EDIT: A very interesting problem. Try it without using patchEntity, and use newEntity instead:

 public function add() { if ($this->request->is('post')) { $data = $this->request->data; // Post process abstracts objects foreach($data['abstracts'] as $index => $abstract) { $abstract['user_id'] = $article->user_id; $abstract['approved'] = 0; $data['abstracts'][$index] = $abstract; } // Build newEntity $article = $this->Articles->newEntity($data, [ 'associated' => ['Abstracts'] ]); // Save our entity with associations if ($this->Articles->save($article, [ 'validate' => false, 'associated' => ['Abstracts'] ])) { $this->Flash->success(__('Your article has been saved.')); return $this->redirect(['action' => 'index']); } // On save fail $this->Flash->error(__('Unable to add your article.')); $this->set('article', $article); } } 

EDIT 2: Your problem looks exactly in your form helper. Your current auxiliary input of the form creates an array of $ data, which looks like this:

 $data = [ 'abstracts' => [ 'body' => 'example text' ], 'category' => 'Science' ]; 

SHOULD look like this:

 $data = [ 'abstracts' => [ ['body' => 'example text'], ['body' => 'Im your second abstract'], ['body' => 'Abstract three!'] ], 'category' => 'Science' ]; 

The problem is this:

 abstracts.body 

which should read like (in array notation):

 // abstracts.0.body echo $this->Form->input('abstracts.0.body', [ 'label' => 'summary of article', 'maxlength' =>'440', 'rows' => '7' ]); 

I believe that this should be the last problem you have encountered.

+3
source

Source: https://habr.com/ru/post/986745/


All Articles