CakePHP中的HABTM表单验证

时间:2010-01-11 18:52:27

标签: cakephp

我有一个Projects表和一个Users表,它们通过HABTM关系链接。在“添加”新项目页面中,我有一个复选框部分,用于为新项目选择用户。我希望项目中至少有一个用户。在CakePHP中处理此问题的最佳方法是什么?

7 个答案:

答案 0 :(得分:19)

试试这个:

// app/models/project.php
/**
 * An additional validation check to ensure at least one User is
 * selected. Spoofs Cake into thinking that there are validation
 * errors on the Project model by invalidating a non-existent field
 * on the Project model, then also invalidates the habtm field as
 * well, so when the form is re-displayed, the error is displayed
 * on the User field.
 **/
function beforeValidate() {
  if (!isset($this->data['User']['User'])
  || empty($this->data['User']['User'])) {
    $this->invalidate('non_existent_field'); // fake validation error on Project
    $this->User->invalidate('User', 'Please select at least one user');
  }
  return true;
}

答案 1 :(得分:12)

我偶然发现了同样的问题,但现在 - 3年后 - CakePHP 2.3

要清楚; Group拥有并属于User。我有一个这样的表格:

// View/Groups/add.ctp
echo $this->Form->input('name');
echo $this->Form->input('User');

使用验证规则,如user448164的答案:

// Model/Group.php
public $validate = array(
    'User' => array(
        'rule' => array('multiple', array('min' => 1)),
        'message' => 'Please select one or more users'
    )
);

这不起作用,谷歌搜索后,我发现这个问题仍然不是最好的解决方案。然后我尝试了几件事,发现这很好用:

// View/Groups/add.ctp
echo $this->Form->input('name');
echo $this->Form->input('Group.User');

方式太简单的解决方案,但不得不深入研究,以找出它的工作原理。

希望有一天能帮到某人。

CakePHP 2.4.x的更新(也可能是2.3.x)

当我写这个答案时,我使用的是CakePHP 2.3.x.当时它可以完美地用于验证和保存数据。现在,当使用CakePHP 2.4.x在新项目上应用相同的代码时,它不再起作用了。

我使用以下代码创建了一个测试用例:

$data = array(
    'User' => array(
        'Client' => array(8)
    ),
);
$this->User->create();
$this->User->saveAll($data);

我的第一个想法是:保存一切意味着保存所有“根”模型,这对我来说真正有意义。要保存比“根”更深的保存,您必须添加deep选项。所以我最终得到了以下代码:

$data = array(
    'User' => array(
        'Client' => array(8)
    ),
);
$this->User->create();
$this->User->saveAll($data, array('deep' => true));

像魅力一样!快乐的编码。的:)

更新(2014/03/06)

再次遇到同样的问题,在这种情况下使用hasMany代替habtm。好像它的行为方式相同。但我发现自己再次寻找这个答案,并感到困惑。

我想明确指出,在输入中使用Group.User代替User是关键。否则,它将不会使用User模型验证。

答案 2 :(得分:6)

我刚刚在一个项目中看到了他自己的问题并且遇到了一个稍微优雅的解决方案,只要你只处理一个habtm关系并且你需要确保至少选中一个复选框。

因此,例如,您正在编辑项目,并希望它与至少一个用户

相关联

将此添加到beforeValidate()

//检查habtm模型并添加到数据

  foreach($this->hasAndBelongsToMany as $k=>$v) {
   if(isset($this->data[$k][$k]))
   {
    $this->data[$this->alias][$k] = $this->data[$k][$k];
   }
  }

在验证规则中添加以下内容:

'User' => array(
   'rule' => array('multiple', array('min' => 1)),
   'message' => 'Please select one or more users'
  )

答案 3 :(得分:2)

teknoid的博客在这里为您的问题提供了非常深入的解决方案。最常用的方法是在模型中添加自定义验证,正如您在上面的评论中提到的那样。查看http://teknoid.wordpress.com/2008/10/16/how-to-validate-habtm-data/

从文章中,Tag HABTM Post(:: Project HABTM Users):

  

首先,我们验证Tag模型   使用表单中的数据来确保   至少选择了一个标签。如果   所以,我们保存邮政和相关   标签

答案 4 :(得分:2)

CakePhp 2.7的2016年更新

在此完整答案:HABTM form validation with CakePHP 2.x

TL; DR;

AppModel.php

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;
 }

 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;
 }

在HABTM的主要模型中:

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

答案 5 :(得分:1)

如果您使用 CakePHP 2.3.x ,除了GuidoH提供的代码之外,您可能还需要将此代码添加到模型中,否则您的HABTM模型数据可能无法保存:

public function beforeSave($options = array()){
  foreach (array_keys($this->hasAndBelongsToMany) as $model){
    if(isset($this->data[$this->name][$model])){
      $this->data[$model][$model] = $this->data[$this->name][$model];
      unset($this->data[$this->name][$model]);
    }
  }
  return true;
}

答案 6 :(得分:0)

根据我对Guido上面答案的评论,我完全使用了Guido的答案,但是在保存到数据库之前我使用beforeSave回调修改了数据。

我在Cake 2.4.5 +上有这个问题

public function beforeSave($options = array()) {
    $temp = $this->data['Group']['User'];
    unset($this->data['Group']['User']);
    $this->data['User']['User'] = $temp;

    return true;
}