2

I want to validate in several models if a given IP and subnet make together a valid network.

I wrote this custom validation function for one model:

public function isValidNetwork($check=null){
    if(isset($this->data[$this->name]['ip']) && isset($this->data[$this->name]['subnet'])){
        $iph = new IpHandler();
        return $iph->isNetwork($this->data[$this->name]['ip'],$this->data[$this->name]['subnet']);
    }
    return false;
}

What is the best practice to reuse this function in other models? Maybe to move the function to AppModel?

But there is another problem, that the keys are not always the same.

Is it possible to overwrite the validation rule to pass only the necessary parameters? For example:

'subnet' => array(
        'rule' => array('isValidNetwork','ip','subnet'),
        'required' => true,
        'message' => 'No valid network given'
    )

public function isValidNetwork($ip, $subnet){...}

1 Answer 1

1

The proper way of reusing your validation method is to implement it in AppModel, or in a custom Behavior.

With regards to allowing your custom validation method to validate different field names, the Cookbook suggests that you use extract_values().

This example has been taken from the docs:

class Post extends AppModel {

    public $validate = array(
        'slug' => array(
            'rule' => 'alphaNumericDashUnderscore',
            'message' => 'Slug can only be letters,' .
                ' numbers, dash and underscore'
        )
    );

    public function alphaNumericDashUnderscore($check) {
        // $data array is passed using the form field name as the key
        // have to extract the value to make the function generic
        $value = array_values($check);
        $value = $value[0];

        return preg_match('|^[0-9a-zA-Z_-]*$|', $value);
    }
}

But I guess you could as well use the extra arguments as the keys to extract the relevant data.

In the $validation array:

'subnet' => array(
    'rule' => array('isValidNetwork','ip','subnet'),
    'required' => true,
    'message' => 'No valid network given'
)

And in your method:

public function isValidNetwork($check, $ipFieldName, $subnetFieldName){
    if(isset($this->data[$this->name][$ipFieldName]) && isset($this->data[$this->name][$subnetFieldName])){
        $iph = new IpHandler();
        return $iph->isNetwork($this->data[$this->name][$ipFieldName],$this->data[$this->name][$subnetFieldName]);
    }
    return false;
}

EDIT

If you want to make use of a single extra parameter, you can do the following:

'ip' => array(
    'rule' => array('isValidNetwork','subnet'),
    'required' => true,
    'message' => 'No valid IP/network given'
)

Your custom validation method would look as follows:

public function isValidNetwork($check, $subnetFieldName){
    list($ip) = array_values($check);

    if(!empty($ip)) && !empty($this->data[$this->name][$subnetFieldName])){
        $iph = new IpHandler();
        return $iph->isNetwork($ip,$this->data[$this->name][$subnetFieldName]);
    }
    return false;
}

See Cookboox 2.x: Data Validation: Adding your own Validation Methods

Sign up to request clarification or add additional context in comments.

3 Comments

I know that possibility. But then i have an unused parameter in my method. That is not clean code. But if it is not possible to avoid the $check parameter, i agree with you.
Perhaps you can use the $check parameter to reference one of the fields, and specify the other through a single extra parameter. This would tie your custom validator to a main field type (e.g. ip), leaving the extra parameter for the other field (e..g subnet).
Edited the answer to include this modification.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.