CakePHP 3.0 Can't save hasMany associated data

此生再无相见时 提交于 2019-12-10 14:58:51

问题


I've problem when saving data with hasMany association

This is my table

1) post table: each item has an unique id.

id | title | ... 
1  | Aloha | ...

2) images table

id | post_id | image   | ...  
1  | 1       | abc.jpg | ...
2  | 1       | efg.jpg | ...

My Model (Table)

Posts Model

// PostsTable.php
<?php

namespace App\Model\Table;

use Cake\ORM\Query;
use Cake\ORM\Table;
use Cake\Validation\Validator;

class PostsTable extends Table {
     public function initialize(array $config) {
        $this->table('posts');
        $this->displayField('title');
        $this->primaryKey('id');
        $this->addBehavior('Timestamp');
        $this->hasMany('Images', [
           'foreignKey' => 'id'
        ]);
     }
}

...

Images Model

// ImagesTable.php
<?php

namespace App\Model\Table;

use Cake\ORM\Query;
use Cake\ORM\Table;
use Cake\Validation\Validator;

class ImagesTable extends Table {
     public function initialize(array $config) {
        $this->table('images');
        $this->displayField('id');
        $this->primaryKey('id');
        $this->addBehavior('Timestamp');
        $this->belongsTo('Posts');
     }
}

...

My Controller

// PostsController.php
...
public function add() {
    $post = $this->Posts->newEntity($this->request->data, [
        'associated' => ['Images']
    ]);

    if ($this->request->is('post')) {
        if ($this->Posts->save($post, ['associated' => ['Images']])) {
            $this->Flash->success('The post has been saved.');
            return $this->redirect(['action' => 'index']);
        } else {
            $this->Flash->error('The post could not be saved. Please, try again.');
        }
    }

    $this->set('post', $post);
}

...

My Template

// add.ctp
<?= $this->Form->create($post); ?>

<?php echo $this->Form->input('title'); ?>

<?php echo $this->Form->input('images.0.image'); ?>
<?php echo $this->Form->input('images.1.image'); ?>
<?php echo $this->Form->input('images.2.image'); ?>

<?= $this->Form->button(__('Submit'), ['class' => 'button-green']) ?> 

<?= $this->Form->end() ?>

Input array result Debug

[
   'title' => 'Hello',
   'images' => [
       (int) 0 => [
           'image' => 'testa.jpeg'
       ],
       (int) 1 => [
           'image' => 'testb.jpeg'
       ],
       (int) 2 => [
           'image' => 'testc.jpeg'
       ]
   ]
]

(Update) debug($post)

object(App\Model\Entity\Story) {

    'new' => true,
    'accessible' => [
        'title' => true,
        'images' => true
    ],
    'properties' => [
        'title' => 'Hello',
        'images' => [
            (int) 0 => object(App\Model\Entity\Image) {

                'new' => true,
                'accessible' => [
                    'post_id' => true,
                    'image' => true,
                    'post' => true
                ],
                'properties' => [
                    'image' => 'testa.jpeg'
                ],
                'dirty' => [
                    'image' => true
                ],
                'original' => [],
                'virtual' => [],
                'errors' => [],
                'repository' => 'Images'

            },
            (int) 1 => object(App\Model\Entity\Image) {

                'new' => true,
                'accessible' => [
                    'post_id' => true,
                    'image' => true,
                    'post' => true
                ],
                'properties' => [
                   'image' => 'testb.jpeg'
                ],
                'dirty' => [
                    'image' => true
                ],
                'original' => [],
                'virtual' => [],
                'errors' => [],
                'repository' => 'Images'

            },
            (int) 2 => object(App\Model\Entity\Image) {

                'new' => true,
                'accessible' => [
                    'post_id' => true,
                    'image' => true,
                    'post' => true
                ],
                'properties' => [
                    'image' => 'testc.jpeg'
                ],
                'dirty' => [
                    'image' => true
                ],
                'original' => [],
                'virtual' => [],
                'errors' => [],
                'repository' => 'Images'

            }
        ]
    ],
    'dirty' => [
        'title' => true,
        'images' => true
    ],
    'original' => [],
    'virtual' => [],
    'errors' => [],
    'repository' => 'Stories'

}

I can't figure out what I am doing wrong

Thanks


回答1:


I haven't looked everything, but I saw there is an error in your association declaration:

$this->hasMany('Images', [
    'foreignKey' => 'id'
]);

The docs say:

foreignKey: the name of the foreign key found in the other model. This is especially handy if you need to define multiple hasMany relationships. The default value for this key is the underscored, singular name of the actual model, suffixed with ‘_id’.

So it should be:

$this->hasMany('Images', [
    'foreignKey' => 'post_id'
]);

or even:

$this->hasMany('Images');



回答2:


I've just finished my 3-hour tour with saving hasMany content along with the main model. This struggle seems to be even worse, if considered saving many main model's objects with many associated items.

  1. Foreign key in hasMany relationship is the singular name of the current model (entity) with _id suffix, so it's like:

    class MainModel extends Table {
    ...
    public function initialize(array $config) {
    ...
    // remember the "s" at the end of the name
    $this->hasMany('VeryWeirdCalleds', [
            'className' => 'VeryWeirdCalleds',
            'foreignKey' => 'main_model_id',
            'propertyName' => 'very_weird_calleds'
        ]);
    ...
    }
    ...
    }
    

Then, you set the accessible in the MAIN Entity, so that the MAIN model can save the association based on "very_weird_calleds" index:

class MainModel extends Entity {
    protected $_accessible = [
        ...
        'very_weird_calleds' => true,
    ];
}

And the last (but not least): the Controller save. It's usually the hardest part to overcome, due to the fact, that docs do not clarify the whole process in detail:

class MainModelsController extends AppController {

public function add($data) {
        $data = [
            [
                'name' => 'Hello', 
                'body' => 'Bla bla', 
                'very_weird_calleds' => [
                    [
                        'name' => 'Very Weird Called'
                    ]
                ]
            ]
        ];
        foreach ($data as $record) {
            $main = $this->MainModels->newEntity($record);

            if(isset($record['images']) && !empty($record['images'])) {
                foreach($record['images'] as $record_image) {
                    $image = $this->MainModels->VeryWeirdCalleds->newEntity();
                    $image->IMAGE = $record_image['IMAGE'];
                    $import->very_weird_calleds[] = $image;
                }
            }
            if (!$this->MainModels->save($main)) {
                $this->Flash->error('The main model could not be saved. Please, try again.');
            }
        }
    }

Explanation? First of all, we loop through the data, previously prepared as follows:

[ 'main', 'model', 'data', 'association_accessible_property' => [ 'associated_data' ] ] ]

Then we create new entries for associated data, using the same method as for the main model. The last thing, is to add those associated Entities to the main model Entity.

Pay an extreme attention to the names given in this example. The 's'-es and CamelCases are not coincidental.




回答3:


try this :

<?php echo $this->Form->input('0.Images.image'); ?>
<?php echo $this->Form->input('1.images.image'); ?>
<?php echo $this->Form->input('2.images.image'); ?>

with int before , according with http://book.cakephp.org/3.0/en/views/helpers/form.html#field-naming-conventions



来源:https://stackoverflow.com/questions/27398100/cakephp-3-0-cant-save-hasmany-associated-data

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!