在 Cakephp 3 中保存关联模型

Posted

技术标签:

【中文标题】在 Cakephp 3 中保存关联模型【英文标题】:Saving associated models in Cakephp 3 【发布时间】:2015-05-07 13:38:34 【问题描述】:

我有一个收集关于一篇文章的数据的表单,我想保存该数据,以及一个名为 Abstract 的模型,其中一篇文章包含许多摘要。我的模型如下所示:

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;


还有

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;
    

我的输入表单有一个名为“abstracts.body”的字段,在我的 ArticlesController 中我有这个功能:

  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);
  

我的摘要表非常简单:

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

通过调试,我可以看到我的 $data 中有正确的“摘要”数组(在 add() 中),但它似乎从未尝试将其保存到数据库中。有人可以指出我的错误吗?谢谢!

【问题讨论】:

请在调用保存前显示debug((string)$article) 拯救了我的一天 :) 带有相关位的 patchEntity()。 【参考方案1】:

知道了。

我在这里开始出错了:

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

因为它是一个 hasMany 关系,所以我需要将该输入设为“abstracts.0.body”

然后 LeWestopher 的其余答案将起作用-向我要从 Controller 填写的字段添加索引,因此 $data[abstracts][0]['user_id'] => ... 等等.谢谢!

【讨论】:

完美!很高兴你明白了。【参考方案2】:

您错误地对 $data['abstracts'] 数组进行了后期处理,导致关联未保存。 $data['abstracts'] 应该是一个 Abstracts 数组。您的问题出在此处:

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

你应该可以很容易地解决这个问题,只需将其更改为:

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

这应该正确地遍历您的摘要数组,适当地设置 user_id 和批准的键,然后它应该正确保存。

Cakephp 3.x Documentation on Saving Associations

编辑:确实非常有趣的问题。尝试不使用patchEntity,而是单独使用newEntity:

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);
         
    

编辑 2: 您的问题看起来肯定出在您的表单助手中。您当前的表单助手输入创建了一个 $data 数组,如下所示:

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

应该是这样的:

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

问题出在:

abstracts.body

应该读作(数组点表示法):

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

我相信这应该是您遇到的最后一个问题。

【讨论】:

还是不行。我不认为你是对的,因为我的问题在那里(或者至少,我唯一的问题不在那里)。我知道这一点,因为我可以注释掉整个部分,但它仍然没有插入。例如。 //$data['abstracts']['user_id'] = $article->user_id; //$data['abstracts']['approved'] = 0;行为完全相同。我的表单看起来像: echo $this->Form->input('abstracts.body', ['label' => 'summary of article', 'maxlength' =>'440', 'rows' => '7' ]); 检查我对答案的编辑,如果该解决方案不起作用,请在处理之前和之后发布您的 $data 数组的 debug() 副本。 另外,这可能无关紧要,但请检查 AbstractEntity.php 中的 $_accessible 属性,您可能没有将“body”属性设置为可通过批量赋值进行设置(使用 newEntity 和 patchEntity)。我不认为是这种情况,因为您在保存功能上设置了 'validate => false',但我不确定这是否也会关闭关联实体的验证。 还是不行。我没有抽象实体文件。 $data = Array ([abstracts] => Array ([body] => 示例文本) [category] ​​=> Science) 而我的 sql 调试仅显示:INSERT INTO 文章(创建、修改、类别)VALUES ('2015-05-07 14:40:56', '2015-05-07 14:40: 56', '科学')

以上是关于在 Cakephp 3 中保存关联模型的主要内容,如果未能解决你的问题,请参考以下文章

CakePHP 3:保存关联模型失败

CakePHP - 如何在保存时将关联记录添加到模型中?

Cakephp 3 保存关联属于ToMany

在 CakePHP 中保存时如何验证关联模型是不是存在

CakePHP 3 保存 BelongsToMany 关联未知类型“”错误

CakePHP 保存非常深的关联模型