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){...}
Inigo Flores
  • 4,461
  • 1
  • 15
  • 36
Michael
  • 35
  • 3

1 Answers1

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

Inigo Flores
  • 4,461
  • 1
  • 15
  • 36
  • 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. – Michael Jan 15 '16 at 19:04
  • 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`). – Inigo Flores Jan 15 '16 at 19:15
  • Edited the answer to include this modification. – Inigo Flores Jan 15 '16 at 19:22