Rob Wilkerson
Rob Wilkerson

Reputation: 41236

Change validation rules on the fly

I'm working on a form that contains user data, specifically a phone number field. The phone number typically isn't required so the only validation rule in the model is the usphone rule. However, if the user is submitting this form, the phone number becomes necessary. I thought I'd be able to simply add a validate rule on the fly, set the model and call the validates method, but either I'm doing it wrong or it's not working the way I expected.

In my controller:

# Update a few validation rules that are specific to this context
$this->Proposal->Requestor->validate['phone_number']['notempty'] = array(
  'rule'       => 'notEmpty',
  'message'    => 'Please enter a phone number so can can contact you with any questions about the work.',
  'allowEmpty' => false,
  'required'   => true,
);

$validationErrors = array();
$this->Proposal->Requestor->set( $this->data['Requestor'] ); # $this->data['Requestor']['phone_number'] only (no other requestor data)
if( !$this->Proposal->Requestor->validates( array( 'fieldList' => array( 'phone_number' ) ) ) ) {
  $validationErrors['Requestor'] = $this->Proposal->Requestor->validationErrors;
}

No errors are reported, even if I leave the phone number field empty. In this case, the only information I'm requesting from the user is their phone number, so the rest of the Requestor data is empty, but I've tried merging in the rest of the user data and I get the same result. If I remove the fieldList option, I get an error on a different field, but still nothing on the empty phone number.

Any idea what I'm missing here? I've been monkeying around with this for hours now and I just haven't found the right answer.

Thanks.

Upvotes: 3

Views: 3117

Answers (2)

Rob Wilkerson
Rob Wilkerson

Reputation: 41236

The solution ended up being twofold:

  1. I had existing rule on the phone_number field that forced the value to be a US phone number. That rule also set allowEmpty to true and required to false. I wanted to catch an empty value so I could display a particularly precise message.
  2. I had to update the existing rule to flip the allowEmpty and required values and also add a new rule with its last value set to true.

The final change, added in my controller action looks like this:

$this->Proposal->Requestor->validate = Set::merge(
  $this->Proposal->Requestor->validate,
  array(
    'phone_number' => array(
      'notempty' => array(
        'rule'       => 'notEmpty',
        'message'    => 'Please enter a phone number so can can contact you with any questions about the work.',
        'allowEmpty' => false,
        'required'   => true,
        'last'       => true,
      ),
      'usphone' => array(
        'allowEmpty' => false,
        'required'   => true,
      ),
    )
  )
);

I can't remember whether I verified that the change to the existing usphone rule was strictly necessary given the last value of the new rule, but this combination is working fine.

Upvotes: 2

Related Questions