如何在CakePHP中验证所需的关联存在?

如何在CakePHP中验证所需的关联存在?,cakephp,cakephp-3.8,Cakephp,Cakephp 3.8,我的项目和我的Medios模型之间有一个工作关系。如果我添加了一个新的Proyecto实体,我可以从注册的medio中进行选择,并且所有内容都已充分保存。问题是,无论我是否选择任何Medio,实体都已正确保存,我希望它成为表单中的必填字段 我尝试在表单中添加“required=>true”,在ProyectoTable中添加“$validator->notEmpty”,但没有成功。(即使未选择Medio,也会保存表单。) 我一直在阅读CakePHP 3.x文档,但我一直没有找到正确的方法来验证相

我的项目和我的Medios模型之间有一个工作关系。如果我添加了一个新的Proyecto实体,我可以从注册的medio中进行选择,并且所有内容都已充分保存。问题是,无论我是否选择任何Medio,实体都已正确保存,我希望它成为表单中的必填字段

我尝试在表单中添加“required=>true”,在ProyectoTable中添加“$validator->notEmpty”,但没有成功。(即使未选择Medio,也会保存表单。)

我一直在阅读CakePHP 3.x文档,但我一直没有找到正确的方法来验证相关数据的存在。我错过了什么?(我想我应该添加一些特殊规则,但我不知道应该如何以及在哪里添加。)

我的模型:

class ProyectosTable extends Table
{
    public function initialize(array $config)
    {
        parent::initialize($config);

        [...]
        
        $this->belongsToMany('Medios', [
            'foreignKey' => 'proyecto_id',
            'targetForeignKey' => 'medio_id',
            'joinTable' => 'medios_proyectos',
        ]);
    }

    public function validationDefault(Validator $validator)
    {
        [...]
        
            $validator
            ->requirePresence('medios', 'create')
            ->notEmpty('medios');
            
        return $validator;
    }
}
我的控制器:

public function add()
{
    $proyecto = $this->Proyectos->newEntity();
    if ($this->request->is('post')) {
        $partida = $this->Proyectos->patchEntity($proyecto, $this->request->getData());
        if ($this->Proyectos->save($proyecto)) {
            $this->Flash->success('El proyecto ha sido salvado.');

            return $this->redirect(['action' => 'index']);
        }
        $this->Flash->error('El proyecto no pudo ser salvado.');
    }

    $medios = $this->Proyectos->Medios->find('list', ['limit' => 200]);
    $this->set(compact('proyecto','medios'));
}
我的看法是:

<?= $this->Form->create($proyecto) ?>
    [...]
    <?= $this->Form->control('medios._ids', ['options' => $medios,'required' => true]); ?>
    [...]
    <?= $this->Form->button('submit') ?>
<?= $this->Form->end() ?>

[...]
[...]

我已经尝试在模型中将其更改为“$validator->requirePresence('medios.\u ids','create')->notEmpty('medios.\u ids');”,但随后该视图向我抛出了“无法保存,必填字段”错误,无论我选择一个、全部还是根本没有Medio。

多选控件确实有这样一个隐藏的回退:


因此,当未选择任何内容时,该字段仍然存在,表示选择为空。使用
\u id
您正在创建一个嵌套结构,因此为
medios
提交的值将永远不会被解释为空,您将收到如下内容:

[
“medios”=>[
“_id”=>”
]
]
所以
notEmpty
规则当然不适用于这里。此外,验证规则字段名不支持点语法,它们严格映射到一级字段

例如,您可以为
medios
字段使用嵌套的验证器,该验证器的规则将应用于
medios
下嵌套的字段。大致如下:

public函数validationDefault(Validator$Validator)
{
// ...
$validator
->需求代表('medios','create')
->addNested('medios',$this->getValidator('medios');
返回$validator;
}
公共函数validationMedios(Validator$Validator)
{
$validator
->需求代表(“ID”)
->注空(“ID”);
返回$validator;
}
另见


太棒了!那很有效!♥ 我知道一定是这样的,但我不知道嵌套验证器。然而,我注意到了另外一件事,我觉得可能与此有关。。。现在,如果我没有选择任何选项,它会告诉我所需的字段,如果我选择其中一个或多个,它会很好地保存实体。但是当我试图编辑实体时,在视图中没有选择任何选项(因此它没有加载关联),我必须重新输入它们,否则我仍然会得到“字段不应为空”。我遗漏了什么?@DamiánFraustro在没有看到代码的情况下很难说,但是传递给表单的实体上没有相关数据,这当然是一个可能的原因。哦!当然非常感谢。我没有在控制器的编辑操作中添加“包含”。当然,没有传递任何相关数据!现在一切都好了。