2012-06-27 108 views
1

什么是我想要做之间的验证?
我有三个字段(1隐藏,一个id),并且用户必须以通过验证完成其他两个中的一个。
因此,用户应该验证失败如果这两个字段为空,但如果一个人完成传递。选择字段


一个0 B真
A B 0真
A 0 0假

我使用CakePHP V2.1.3所以有机会获得新的验证规则增强。

问题
我似乎无法找到一个可靠的方式在同一时间检查这两个字段。我迄今从model试图寻找$this->data和发现,确认只有在通过数据的单个实例在同一时间。所以似乎没有办法比较这些字段。

我有什么到目前为止

/** 
* Custom validation to see if either of the two fields are set, if neither are, then we fail, if at least one is, we pass 
* @param array $check 
* @return boolean 
*/ 
public function checkAttributes($check){ 
    var_dump($check); 
    var_dump($this->data); 
    echo "<hr>"; 

    // Check for an id value picked from a list 
    if(@is_numeric($check['attribute_value_id']) && isset($this->data['AdvertAttributeValue']['attribute_value_id'])){ 
     return true; 
    } 

    // Check for a date value selected 
    if(@is_array($check['attribute_value_text']) && isset($this->data['AdvertAttributeValue']['attribute_value_text'])){ 
     return true; 
    } 

    // Check for a text value 
    if(@is_string($check['attribute_value_text']) && isset($this->data['AdvertAttributeValue']['attribute_value_text'])){ 
     return true; 
    } 

    return false; 
} 

这似乎并没有这样的伎俩,因为我觉得它不能检查$this->data因为它的实例不包含所有相关领域。

数据
我还要提到的是,我传递一个大的数字阵列。因此,这些领域多次出现在页面上,目前12米的尺寸。所以访问它们直接通过$this->data会很难,因为他们没有被命名的尺寸,但$this->data['Model'][<num>]['field'] = value


验证

public $validate = array(
    'attribute_value_id'=>array(
     'notempty'=>array(
      'rule'=>'checkAttributes', 
      'message'=>'Please select a value for your attribute', 
      'required'=>true, 
     ), 
    ), 
    'attribute_value_text'=>array(
     'notempty'=>array(
      'rule'=>'checkAttributes', 
      'message'=>'You must enter text for this attribute', 
      'required'=>true, 
     ), 
    ) 
); 

数据转储
在这里,我会显示上面的var_dump()的输出。我在我的模型两个验证规则,一个用于attribute_value_id也是一个attribute_value_text

// An id field selected from a list 
array // $check 
    'attribute_value_id' => string '1' (length=1) 
array // $this->data 
    'AdvertAttributeValue' => 
    array 
     'attribute_value_id' => string '1' (length=1) 
     'id' => string '' (length=0) 

// A text field 
// Validating first time around on the id field 
array // $check 
    'attribute_value_id' => string '' (length=0) 
array // $this->data 
    'AdvertAttributeValue' => 
    array 
     'attribute_value_id' => string '' (length=0) 
     'id' => string '' (length=0) 
     'attribute_value_text' => string '50' (length=2) 
// Validating second time around on the text field 
array // $check 
    'attribute_value_text' => string '50' (length=2) 
array // $this->data 
    'AdvertAttributeValue' => 
    array 
     'attribute_value_id' => string '' (length=0) 
     'id' => string '' (length=0) 
     'attribute_value_text' => string '50' (length=2) 
// A date field 
array // $check 
    'attribute_value_id' => string '' (length=0) 
array // $this->data 
    'AdvertAttributeValue' => 
    array 
     'attribute_value_id' => string '' (length=0) 
     'id' => string '' (length=0) 
     'attribute_value_text' => 
     array 
      'month' => string '06' (length=2) 
      'day' => string '28' (length=2) 
      'year' => string '2012' (length=4) 
+1

验证发生在什么阶段?例如,如果在保存期间,'$ this-> data'应该包含从控制器传入'Model :: save()'的所有内容。当你说“验证只传递一个数据实例”时,你是什么意思? – eaj

+0

@eaj这是保存期间。通过传递一个实例,我的意思是一个单一的数组维度。所以在我的数组中,只有一个维度被传递给自定义验证函数。所以如果你有5个字段,你一次只能得到一个。我会添加一个转储。 –

+0

如果'$ this-> data'没有包含你需要验证的所有信息(就像你在你的问题中所说的那样),那肯定是因为你没有把它全部从你的模型传递到Model :: save()控制器?据我了解,当你调用'save()'的时候,模型的$ this-> data被设置为你传入的数据,然后传递给'validate()'。 (也许你已经解决了这个问题,因为已经过了两周了;我已经离开了。) – eaj

回答

0

saveAll()方法只是调用saveMany()saveAssociated()适当。默认情况下,这些方法会在保存所有数据之前尝试验证所有数据(通过致电validateMany())。然而,正如你可以在the source看到,该函数单独验证每一个项目,所以校验码将不能访问其他记录。

据我所知,你需要在多个记录之间进行交叉验证,然后再保存它们。虽然我从来没有这样做过,但这听起来像是在控制器中进行验证的情况。您可以拨打Model::validate()Model::validateAll()以确保记录的内部一致性。然后你的控制器也可以实现你的交叉记录验证所需的任何逻辑。一旦这样做了,你可以保存与验证禁止拨打:

$this->myModel->saveAll($this->request->data, array('validate'=>false)); 

注意,你做任何在此之前,你有你的数据集模型:

$this->myModel->set($this->request->data); 

我意识到这会在控制器中放置很多额外的代码,理想情况下应该放在模型中。我想这可能是通过模型回调之一完成的,但我不知道如何。

+0

这听起来像是一种合乎逻辑的方法,因为它可以分解为组件,插件或行为。 –

0

你可以利用模型:: $ DATA或型号:: beforeValidate()。

+0

小心地扩大你的答案,使它有帮助吗? –