【问题标题】:Select validation between fields选择字段之间的验证
【发布时间】:2012-06-27 16:15:10
【问题描述】:

我想做什么?
我有三个字段(1 个隐藏,一个 id),用户必须完成另外两个字段之一才能通过验证。
因此,如果两个字段都为空,则用户应该无法通过验证,但如果一个已完成,则通过。

1 2 3
A 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-&gt;data,因为它的实例不包含所有相关字段。

数据
我还应该提到我正在传递一个大型数字数组。因此这些字段在页面上出现多次,目前为 12 维。所以直接通过$this-&gt;data访问它们会很困难,因为它们不是命名维度,而是$this-&gt;data['Model'][&lt;num&gt;]['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)

【问题讨论】:

  • 此验证在哪个阶段进行?例如,如果在保存期间,$this-&gt;data 应该包含您从控制器传递到Model::save() 的任何内容。当您说“验证仅传递数据的单个实例”时,您是什么意思?
  • @eaj 这是在保存期间。通过传递单个实例,我的意思是单个数组维度。所以在我的数字数组中,只有一个维度被传递给自定义验证函数。因此,如果您说 5 个字段,则一次只能传入一个。我会添加一个转储。
  • 如果$this-&gt;data 不包含您需要验证的所有信息(正如您在问题中所说),那肯定是因为您没有从控制器将其全部传递给Model::save()?据我了解,当您调用save() 时,模型的$this-&gt;data 被设置为您传入的数据。这反过来又被传递给validate()。 (那么,也许你已经解决了这个问题,因为现在已经有两个星期了;我已经离开了。)
  • 我正在使用saveAll(),这可能是数据不同的原因。我最终使用 javascript 围绕它进行编码!所以还没有真正解决。

标签: cakephp cakephp-2.1


【解决方案1】:

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

我意识到这会在控制器中添加很多额外的代码,理想情况下应该在模型中。我想有可能通过模型​​回调之一来完成,但我不确定如何。

【讨论】:

  • 这听起来像是一种合乎逻辑的方法,因为它可以分解为组件、插件或行为。
【解决方案2】:

您可以使用 Model::$data 或 Model::beforeValidate()。

【讨论】:

  • 想扩展您的答案以使其有用吗?
猜你喜欢
  • 1970-01-01
  • 2021-05-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-02-24
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多