【问题标题】:BelongsToMany retrieving and deleting correctly, not updating/saving in CakePHP 3.xBelongsToMany 正确检索和删除,而不是在 CakePHP 3.x 中更新/保存
【发布时间】:2021-01-16 00:45:26
【问题描述】:

CakePHP 3.8.13 - 我有一个表模型,它可以从表中检索相关数据并将其删除,但是在更新/添加条目时,由于某种原因它不会更改此数据。所以这似乎是一个正确的设置,但它不会更新/添加它们。简而言之,它是一个“Questions”表和一个“Divisions”表,以及一个名为“questions_divisions”的关系表。在这个关系表中有一个 question_id 和一个 division_id 列。如果我在那里手动添加或删除条目,一切似乎都可以。只是在执行 patchEntity 并保存时,它不执行此操作。这是帖子数据:

  'name' => string 'Some name' (length=8)
  'questiontype_id' => string '1' (length=1)
  'extra' => string '' (length=0)
  'answer' => string '' (length=0)
  'datafield' => string 'Person.firstname' (length=16)
  'divisions' => 
    array (size=1)
      '_ids' => 
        array (size=3)
          0 => string '1' (length=1)
          1 => string '7' (length=1)
          2 => string '5' (length=1)

这是执行的代码(所以上面的post数据,就是$this->request->getData()):

$question = $this->Questions->patchEntity($question, $this->request->getData());
            if ($this->Questions->save($question)) {

所有这些或多或少与应用程序中其他地方发生的不同模型相同,实际上确实添加/更新了部门。我还清除了 /tmp/cache 以防万一,似乎没有奏效。我在这里不知所措。

这是整个表格模型:

<?php

namespace App\Model\Table;

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

/**
 * Questions Model
 *
 * @property \App\Model\Table\QuestiontypesTable|\Cake\ORM\Association\BelongsTo $Questiontypes
 * @property \App\Model\Table\ActivitiesTable|\Cake\ORM\Association\BelongsToMany $Activities
 * @property \App\Model\Table\BookingformsTable|\Cake\ORM\Association\BelongsToMany $Bookingforms
 * @property \App\Model\Table\DivisionsTable|\Cake\ORM\Association\BelongsToMany $Divisions
 *
 * @method \App\Model\Entity\Question get($primaryKey, $options = [])
 * @method \App\Model\Entity\Question newEntity($data = null, array $options = [])
 * @method \App\Model\Entity\Question[] newEntities(array $data, array $options = [])
 * @method \App\Model\Entity\Question|bool save(\Cake\Datasource\EntityInterface $entity, $options = [])
 * @method \App\Model\Entity\Question|bool saveOrFail(\Cake\Datasource\EntityInterface $entity, $options = [])
 * @method \App\Model\Entity\Question patchEntity(\Cake\Datasource\EntityInterface $entity, array $data, array $options = [])
 * @method \App\Model\Entity\Question[] patchEntities($entities, array $data, array $options = [])
 * @method \App\Model\Entity\Question findOrCreate($search, callable $callback = null, $options = [])
 */
class QuestionsTable extends Table {

    public function beforeFind ($event, $query, $options, $primary) {
        $order = $query->clause('order');
        if ($order === null || !count($order)) {
            $query->order([$this->getAlias() . '.name' => 'ASC']);
        }
    }

    /**
     * Initialize method
     *
     * @param array $config The configuration for the Table.
     * @return void
     */
    public function initialize(array $config) {
        parent::initialize($config);

        $this->setTable('questions');
        $this->setDisplayField('name');
        $this->setPrimaryKey('id');

        $this->addBehavior('Search.Search');
        $this->addBehavior('Page');

        $this->hasMany('Questions_divisions', [
            'foreignKey' => 'question_id'
        ]);

        $this->belongsTo('Questiontypes', [
            'foreignKey' => 'questiontype_id',
            'joinType' => 'INNER'
        ]);
        $this->belongsToMany('Activities', [
            'foreignKey' => 'question_id',
            'targetForeignKey' => 'activity_id',
            'joinTable' => 'activities_questions'
        ]);
        $this->belongsToMany('Bookingforms', [
            'foreignKey' => 'questions_id',
            'targetForeignKey' => 'bookingforms_id',
            'joinTable' => 'questions_bookingforms'
        ]);
        $this->belongsToMany('Divisions', [
            'foreignKey' => 'question_id',
            'targetForeignKey' => 'division_id',
            'joinTable' => 'questions_divisions'
        ]);

        //Setup searchfield
        $this->behaviors()->Page->searchSetup($this->behaviors()->Search->searchManager(), $this->searchForm());
    }

    /**
     * Default validation rules.
     *
     * @param \Cake\Validation\Validator $validator Validator instance.
     * @return \Cake\Validation\Validator
     */
    public function validationDefault(Validator $validator) {
        $validator
                ->integer('id')
                ->allowEmpty('id', 'create');

        $validator
                ->scalar('name')
                ->maxLength('name', 500)
                ->requirePresence('name', 'create')
                ->notEmpty('name');

        $validator
                ->scalar('extra')
                ->maxLength('extra', 500)
                ->allowEmpty('extra');

        $validator
                ->scalar('answer')
                ->maxLength('answer', 1500)
                ->allowEmpty('answer');

        $validator
                ->scalar('datafield')
                ->maxLength('datafield', 500)
                ->requirePresence('datafield', 'create')
                ->notEmpty('datafield');

        return $validator;
    }

    /**
     * Returns a rules checker object that will be used for validating
     * application integrity.
     *
     * @param \Cake\ORM\RulesChecker $rules The rules object to be modified.
     * @return \Cake\ORM\RulesChecker
     */
    public function buildRules(RulesChecker $rules) {
        $rules->add($rules->existsIn(['questiontype_id'], 'Questiontypes'));

        return $rules;
    }

    /**
     * Returns an array which describes the search form
     *
     * @return Array with search setup
     */
    public function searchForm() {
        //Set up search form
        $search_data = [['id' => 'name', 'label' => 'Naam', 'type' => 'textfield', 'fields' => ['name']],
            ['id' => 'Questiontypes_id', 'label' => 'Vraagtype', 'type' => 'multiselect', 'fields' => ['Questiontypes.id'], 'options' => $this->Questiontypes->find('list')],
            ['id' => 'datafield', 'label' => 'Dataveld', 'type' => 'textfield', 'fields' => ['datafield']]
        ];
        return $search_data;
    }

}

【问题讨论】:

  • 在补丁前后调试$question。另请解释保存时到底发生了什么,从您的解释中不清楚是只有部分数据没有被保存,还是根本没有保存。
  • @ndm 很抱歉这里没有完全清楚。一切都正确保存,没有额外添加的“部门”。这就是 belongsToMany('Divisions') 位。它确实检索它。保存后,分区(手动添加时)在路径/保存之前和之后都可用。只是不像我编辑它们的方式。因此,如果我像上面的帖子数据一样发送 3 个 id 作为分区,它仍然只能从数据库中获取 1 ......出于某种原因,它不会让我更新它,而只会检索(并且在执行 delete() 时,它也会从关系表中删除)。
  • 修补前后$question 是什么样子的?特别是,divisions 属性中有什么,该属性是否被标记为脏?
  • 感谢@GregSchmidt,您的调试让我进一步研究了这个模型,并发现accessible 也需要这个列名。这就是我实际上忘记添加的内容,现在它就像一个魅力。

标签: cakephp model cakephp-3.0 model-associations


【解决方案1】:

似乎在 $_accessible 数组(在模型/实体内)中添加此列可以解决问题...这就是为什么它可以检索数据,但不能编辑它 - 因此可能是“可访问”?不确定这是否是正确的名称,但是嘿..

protected $_accessible = [
   'name' => true,
   'extra' => true,
   'answer' => true,
   'datafield' => true,
   'questiontype_id' => true,
   'questiontype' => true,
   'activities' => true,
   'bookingforms' => true,
   'divisions' => true // this did the trick!
];

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-10-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多