在CakePHP 3中验证翻译的实体

时间:2017-11-17 12:08:27

标签: php cakephp cakephp-3.0

我在CakePHP3中验证I18N字段时遇到了一些困难。

翻译行为设置如下:

$this->addBehavior('Translate', [
    'fields' => ['name', 'body', 'slug'],
    'validator' => 'default'
]);

像这里宣传的那样:https://book.cakephp.org/3.0/en/orm/behaviors/translate.html#validating-translated-entities

核心验证工作正常。我在validationDefault函数中有一个验证规则,它检查name是否为空并且工作正常。不过,我还想在此验证之上添加一些应用程序规则。 “name”字段应具有唯一值。我不想允许具有相同翻译名称的多个实体。

这段代码显然不起作用。 CakePHP文档对此事也非常沉默。

public function buildRules(RulesChecker $rules) {
    // prevent duplicate creation
    $rules->add($rules->isUnique(['name']));
    return $rules;
} 

这实际上可行吗? 感谢

1 个答案:

答案 0 :(得分:1)

您正在做的是为主模型上的name字段创建规则,这不会影响翻译。没有内置功能,该行为仅通过使用validationTranslated()方法协助验证规则,以防它存在于模型类中,它对应用程序规则没有帮助。

您必须创建一个自定义应用程序规则,通过匹配fieldlocalemodelcontent字段来检查转换表。这句话:

$rules->add(
    function (EntityInterface $entity) {
        $behavior = $this->behaviors()->get('Translate');
        $association = $this->association($behavior->getConfig('translationTable'));

        $result = true;
        foreach ($entity->get('_translations') as $locale => $translation) {
            $conditions = [
                $association->aliasField('field') => 'name',
                $association->aliasField('locale') => $locale,
                $association->aliasField('content') => $translation->get('name')
            ];

            if ($association->exists($conditions)) {
                $translation->setErrors([
                    'name' => [
                        'uniqueTranslation' => __d('cake', 'This value is already in use')
                    ]
                ]);

                $result = false;
            }
        }

        return $result;
    }
);

请注意,这使用关联对象而不是目标表,这将确保自动应用更多条件,如模型名称。

此外,这需要手动设置实体上的错误,因为它们是嵌套的,规则检查器不支持,目前它只能在第一级实体上设置错误(请参阅errorField选项)。

还应该注意,可以修改转换表关联的规则检查器(通过Model.buildRules事件),但是这会导致在将要放置的新实体上设置错误在主实体上的一个单独的属性(默认为_i18n)中,表单助手将找不到错误,因此必须手动读取错误,这有点烦人。

另见