Log in

View Full Version : Validating that keys exist in an array



JasonDFR
02-15-2009, 10:55 PM
I want to provide an array of parameters to a function. I am not so concerned with the arrays values as I am with the keys, as validation on the values will have been done prior. Actually it is unlikely that the array will be missing any values by this point, but I thought I better do at least a little validation here.

Here is what I have. Is there a better way.


public function addLink($params) {

if ( !is_array($params) )
throw new Exception('addLink must receive an array.');


$validKeys = array('l_url', 'l_title', 'l_description');

foreach ( $validKeys as $key ) {

if ( !array_key_exists($key, $params))
throw new Exception('Check the $params supplied to addLink()');

}

$this->insert($params);

}

Twey
02-15-2009, 11:24 PM
PHP convention would have you just ignore extraneous keys. Use the ones you need, and discard any others.

Additionally, I think the 'l_' prefix is a little redundant. The function is called addLink(); you're hardly going to be talking about the title of a book of Greek philosophy, are you?

You can discard unnecessary keys by combining array_intersect_key (http://www.php.net/array-intersect-key)() with array_fill_keys (http://www.php.net/array-fill-keys)():
function array_only($arr, $keys) {
return array_intersect_key($arr, array_fill_keys($keys, true));
}Your function then becomes:
public function addLink($params) {
if (!is_array($params))
throw new Exception('addLink must receive an array.');

return $this->insert(array_only($params, array('url', 'title', 'description')));
}

JasonDFR
02-16-2009, 06:23 AM
I like the idea.

The keys are database columns, so I have to use the l_ prefix.

Requirements:

l_url, l_description, l_title MUST be keys in the array.
They must have values.


insert(array('l_url'=>'www.dynamicdrive.com',
'l_description'=>'Great Forums',
'l_title'=>'Dynamic Drive')
);

Will work. I don't think anything else will.

This class is part of the Model, so perhaps I am misguided in even trying to do any validation here. I'm just getting into real Model View Controller architecture. I have a lot to figure out.

What do you think Twey? I am starting to think that the validation shouldn't be here at all.

Twey
02-16-2009, 03:39 PM
The keys are database columns, so I have to use the l_ prefix.Just because you have to use it internally doesn't mean you have to expose it to the user. Add them on later.
This class is part of the Model, so perhaps I am misguided in even trying to do any validation here. I'm just getting into real Model View Controller architecture. I have a lot to figure out.The arguments surrounding MVC and validation are complex, and no-one's entirely agreed on how it's best done. Putting the validation in the models is a valid choice (the usual approach, I believe, is to let the developer add whatever they like to the model, and have an isValid() call or similar to tell them whether they got it right; of course, trying to save the model when the data is invalid should result in an exception). This isn't really validation in that sense, though. Validation is about user input; what you're 'validating' here is a different kind of input, from the user of your library rather than the user of your application. The user of your library is a developer, running it on their own server, and therefore can be trusted to provide sane input. Any 'validation' you do is just to ease debugging.

JasonDFR
02-16-2009, 07:10 PM
I don't know if you are familar with Zend Framework, but this is what I have been trying to learn for the past couple days.

As chance would have it, I just received this in an email from the ZF mailing list. Someone else was asking a similar question to mine.


public function insert(array $data)
{
$data = array_intersect_key($data, array_fill_keys($this->info('cols'), ''));
return parent::insert($data);
}

public function update(array $data, $where)
{
$data = array_intersect_key($data, array_fill_keys($this->info('cols'), ''));
return parent::update($data, $where);
}

In the above example $this is an instance of Zend_Db_Table. Basicly it turns a table from your database into an object. All it takes to do this is extending Zend_Db_Table, giving the new class the same name as your table, and supplying one variable that has the same name as your table. It is two lines of code, then you can call $this->insert() like above to do an insert query as long as you are feeding it an array with key values that match your column names. This is Awesome.

J