如何根据实体字段设置规则?

How to set the rules depending on the entity field?

情况

使用 Cake 3.2.6

在我的成本项目中Table,

我有一个buildRules函数

/**
 * 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(['foreign_model_id'], 'ForeignModels'));
    return $rules;
}

我想要的

我的 CostItems 实体有 2 个字段,分别称为 foreign_modelforeign_model_id

foreign_model_id 作为外键。 foreign_model 作为 Table 将成为 CostItems table.

的父项

所以一个典型的记录可以有 foreign_model 作为 GeneralCostCategories 和 foreign_model_id 作为 1。

我试过的

我尝试在 buildRules 函数中记录 $this,但我发现没有任何有用的东西可以让我动态更改此规则。

   $rules->add($rules->existsIn(['foreign_model_id'], 'ForeignModels'));

   $rules->add($rules->existsIn(['foreign_model_id'], $entity->foreign_model));

有多种方法可以解决这个问题,这里有两种。

* 需要说明的是,以下均为未经测试的示例代码!

自定义规则

您可以实施自定义规则,作为回调或作为规则 class,实体将被传递到那里,然后 运行 相应地检查是否存在来自实体的数据。

回调

use Cake\Datasource\EntityInterface;
use Cake\ORM\Rule\ExistsIn;

// ...

$rules->add(
    function (EntityInterface $entity, array $options) {
        $check = new ExistsIn(['foreign_model_id'], $entity->get('foreign_model'));
        return $check($entity, $options);
    },
    '_existsIn',
    [
        'errorField' => 'foreign_model_id',
        'message' => __d('cake', 'This value does not exist')
    ]
);

自定义规则class,src/Model/Rule/MyExitsIn.php

namespace App\Model\Rule;

use Cake\Datasource\EntityInterface;
use Cake\ORM\Rule\ExistsIn;

class MyExistsIn extends ExistsIn
{
    public function __construct($fields)
    {
        parent::__construct($fields, null);
    }

    public function __invoke(EntityInterface $entity, array $options)
    {
        $this->_repository = $entity->get('foreign_model');
        return parent::__invoke($entity, $options);
    }
}
use App\Model\Rule\MyExistsIn;

// ...

$rules->add(
    new MyExistsIn(['foreign_model_id']),
    '_existsIn',
    [
        'errorField' => 'foreign_model_id',
        'message' => __d('cake', 'This value does not exist')
    ]
);

动态构建规则

或者使用 Model.beforeRules 事件,它也接收实体,并即时修改规则检查器对象。

在你的tableclass

use Cake\Datasource\EntityInterface;
use Cake\Event\Event;

// ...

public function beforeRules(Event $event, EntityInterface $entity, \ArrayObject $options, $operation)
{
    /* @var $rulesChecker \Cake\ORM\RulesChecker */
    $rulesChecker = $this->rulesChecker();
    $rulesChecker->add(
        $rulesChecker->existsIn(['foreign_model_id'], $entity->get('foreign_model'))
    );
}

另见