使用 CakePHP 进行 HABTM 表单验证 2.x

HABTM form validation with CakePHP 2.x

我有一个像这样的 HABTM 关系:Post <-> Tag(一个 Post 可以有多个标签,反之亦然)。

这与 Cakephp 生成的多复选框选择一起使用。但是我想每个 Post 至少有一个标签,如果有人试图插入一个孤儿,我会抛出一个错误。

我正在寻找 cleanest/most CakePHP 类似的方法来执行此操作。


这或多或少是这个 HABTM form validation in CakePHP 问题的更新,因为我在我的蛋糕上遇到了同样的问题php 2.7(最后一个蛋糕php 2.x现在在 2016 年获得 php 5.3 支持)并且找不到好的方法。

以下是我认为目前最好的。它使用 cakephp 3.x 行为进行 HABTM 验证。

我选择只在模型中工作,使用最通用的代码。

在您的 AppModel.php 中,设置此 beforeValidate()afterValidate()

class AppModel extends Model {
   /** @var array set the behaviour to `Containable` */
 public $actsAs = array('Containable');

   /**
    * copy the HABTM post value in the data validation scope
    * from data[distantModel][distantModel] to data[model][distantModel]
    * @return bool true
    */
 public function beforeValidate($options = array()){
   foreach (array_keys($this->hasAndBelongsToMany) as $model){
     if(isset($this->data[$model][$model]))
       $this->data[$this->name][$model] = $this->data[$model][$model];
   }

   return true;
 }

   /**
    * delete the HABTM value of the data validation scope (undo beforeValidate())
    * and add the error returned by main model in the distant HABTM model scope
    * @return bool true
    */
 public function afterValidate($options = array()){
   foreach (array_keys($this->hasAndBelongsToMany) as $model){
     unset($this->data[$this->name][$model]);
     if(isset($this->validationErrors[$model]))
       $this->$model->validationErrors[$model] = $this->validationErrors[$model];
   }

   return true;
 }
}

在此之后,您可以像这样在模型中使用验证:

class Post extends AppModel {

    public $validate = array(
        // [...]
        'Tag' => array(
              // here we ask for min 1 tag
            'rule' => array('multiple', array('min' => 1)),
            'required' => true,
            'message' => 'Please select at least one Tag for this Post.'
            )
        );

        /** @var array many Post belong to many Tag */
    public $hasAndBelongsToMany = array(
        'Tag' => array(
            // [...]
            )
        );
}

本回答使用: