...

View Full Version : Variable Argument Lengths



HairyTeeth
10-27-2003, 04:18 AM
Hi all,
Im trying to construct a generic php class to handle form validation, particularly for logins. I have written a method - getFormData() - that accepts as arguments, the associative-array-value(s) of the form element name(s). It also accepts any number of arguments.

The html form is set up like so:


<form action="foo.php">
<input type="text" name="user[Username]" />
<input type="password" name="user[Password]" />
<input type="password" name="user[Confirm Password]" />
<input type="text" name="user[Email Address]" />
<input type="submit" value="Submit" />
</form>

I can pass the array value to the getFormData() method as an argument and it returns the name-value pair for the form. Here is the getFormData() method:


//foo.php
function getFormData()
{
$arg_list = func_get_args();
$cnt = count($_POST[user]);
$fld_name = array_keys($_POST[user]);
$fld_value = array_values($_POST[user]);
$i = 0;

while($i < $cnt)
{
if($fld_name[$i] == $arg_list[$i])
{
$stack[$fld_name[$i]] = $fld_value[$i];
}
$i++;
}
return $stack;
}

//this is how im currently calling the function;
$keys = array_keys(getFormData('Username','Password'));
$vals = array_values(getFormData('Username','Password'));
$c = count(getFormData('Username','Password'));
$j=0;

while($j<$c)
{
print 'Key: '.$keys[$j].' Value: '.$vals[$j].' <br>';
$j++;
}

What I would like to do is to have a series of validation methods that accept as arguments any form element name (thats in the user[] array), have any validation method access the getFormData() method and return the appropriate values. After that I can do whatever validation is necessary. For example:


function foodleBot($args)
{
//get arguments passed to foodleBot;
//pass all $args to getFormData();
//get the return values and validate;
}

//example calls
//foodleBot('Password','Confirm Password');
//foodleBot('Username','Password','Email');

However, I'm having trouble extracting the arguments from the validation function and passing them to getFormData(). In fact, I've confused myself trying different things. For example, this wont work - even if I change the getFormData() return type to an array: ie return array($stack); -


function foodleBot($flds)
{
$args = func_get_args();
$keys = array_keys(getFormData($args));
$vals = array_values(getFormData($args));
$c = count(getFormData($args));
//$c=func_num_args();
$j=0;

while($j<$c)
{
print 'Key: '.$keys[$j].' Value: '.$vals[$j].' <br>';
$j++;
}
}

//example call
foodleBot('Password','Confirm Password');

I forget which, but I think it returns null. It does work if I call it outside a function as per the getFormData() code (way) above. That ways no good because the argument values have to be hardwired.

Any help would be appreciated.

HT

mordred
10-27-2003, 11:34 PM
Your problem is that your getFormData() function does expect a variable number of arguments, which must all be strings, but in foodleBot() you're passing an array instead. Here's a fixed version of it and some minor readability enhancements too:



function getFormData() {
$args = func_get_args();

// is an array passed instead?
if (count($args) == 1 && is_array($args[0])) {
$args = $args[0];
}

$matches = array();
foreach ($_POST['user'] as $key => $value) {
if (in_array($key, $args)) {
$matches[$key] = $value;
}
}
return $matches;
}


P.S: Two nitpickings: Don't call a variable "stack" if you don't use it as one. And don't shorten names like "field" to "fld" and "count" to "cnt" by stripping the vocals - the extra characters typed pay off through enhanced readability and don't really slow the parser down. But that's just me and my standards... :)

HairyTeeth
10-28-2003, 04:54 AM
Mordred, now that is a nice function! Not just because it works so wonderfully :thumbsup: :thumbsup: :thumbsup: , but because of it's brevity. I can now rewrite foodleBot() like this:


function foodleBot()
{
$args = func_get_args();
$item = getFormData($args);

foreach($item as $keys=>$value)
{
print 'Key: '.$keys.' Value: '.$value.' <br>';
}
}

... which is far, far better than how I had been approaching it before (I had used the foreach construct in other incarnations of foodleBot() but those functions never turned out as neat as this one).
Between making this post and reading your reply, I had discovered that the problem lay somewhere with the the variable datatype but I was still a long way off from a solution like yours.

Regarding your nitpickings :) ..
I used $stack because this line:

$stack[$fld_name[$i]] = $fld_value[$i];

has the same effect as array_push(), which treats arrays as a stack - but you are right, it isn't a stack at all.

I agree with the points you make about variable names and readability. PHP has coding conventions that I must learn (not that I've seen $fld as a coding convention anywhere! )

Thanks for your help and constructive critisims Mordred!

Cheers.

mordred
10-28-2003, 11:46 AM
Regarding the standard PHP coding conventions, many people adhere (more or less) to those used for the PEAR project:
http://pear.php.net/manual/en/standards.php

About the style of variable/method/class naming, I found this link quite helpful and inspiring:
http://www.objectmentor.com/resources/articles/naming.htm#Pronounceable

HairyTeeth
10-28-2003, 11:06 PM
Thanks for the links Mordred - bookmarked for later digestion.

I would just like to confirm my understanding of the code snippet below and ask a couple of questions along the way:

This snippet:

$args = func_get_args();
if (count($args) == 1 && is_array($args[0])) {
$args = $args[0];
}

If either (a) an array is passed as an argument to getFormData() or (b) a single non-array argument such as 'Username' is passed as an argument to getFormData(), then count($args) will = 1.

If an array is passed then the value of $args[0] will be of type Array (gettype() = array) and is_array($args[0]) will be true (as will the whole condition).

Otoh, if a single string argument is passed, the value of $args[0] will be the value of that argument; the type will not be Array (eg. gettype() = string) and the is_array() test will return false.

$args = $args[0] formally implements (redeclares?, casts?, reassigns?) the $args variable as an array() with key=>value pairs. Is it that the func_get_args() implements arrays differently to array(), say, as a list?

As for the rest, I'm happy with my understanding. The in_array() function certainly saves a few lines of code.

Thanks for youre time Mordred.

HT

mordred
10-29-2003, 12:06 AM
Originally posted by HairyTeeth
If either (a) an array is passed as an argument to getFormData() or (b) a single non-array argument such as 'Username' is passed as an argument to getFormData(), then count($args) will = 1.


Not quite: count($args) just gives you the number of argumetns passed to the function. But I think you meant that in your (a) part. It is the first part of a barrier that checks if the only argument passed is an array.



If an array is passed then the value of $args[0] will be of type Array (gettype() = array) and is_array($args[0]) will be true (as will the whole condition).


Yes, that's correct.


Otoh, if a single string argument is passed, the value of $args[0] will be the value of that argument; the type will not be Array (eg. gettype() = string) and the is_array() test will return false.


Yes, and that makes the whole AND-condition return false, thus neglecting the next part.



$args = $args[0] formally implements (redeclares?, casts?, reassigns?) the $args variable as an array() with key=>value pairs. Is it that the func_get_args() implements arrays differently to array(), say, as a list?


I'd say the more correct term would be: $args = $args[0] means that the value of $args[0] will be assigned to $args. By doing this, we overwrite the former value stored in $args. I guess you could also call that a "reassignment" of $args.

It's definitely not a cast, a cast is always an explicit type coercion, like $args = (int) $foo. The "(int)" is a cast operator.

The type of array is not really a key-value pair array, but OTOH it is. Sounds confusing? That's due to PHPs arrays, they always have keys and values. But generally one thinks of key-value arrays (or associative arrays) as arrays with string keys, as opposed to numerically indexed arrays.

But we don't enforce a certain kind of array through this assignment. We just suppose it's a list with numerical indices, but it is not guaranteed it is. Anyway, later down with in_array(), only the values are what interests us, so we don't get concerned what keys this array might or might not have.



As for the rest, I'm happy with my understanding. The in_array() function certainly saves a few lines of code.


I can only recommend experimenting with the big array function library that ships with PHP. There are some real goodies in there, such as array_map(), array_filter() and array_walk(). If you learn to use them, you can save yourself a lot of for-loop writing in the future... and believe me, writing for loops is not very... eh... elegant. The "advanced" array features provide some kind of beauty through simplicity, if you understand what I mean here. Ok, I stop with this esoteric rambling. For now. ;)

HairyTeeth
11-08-2003, 08:15 AM
Originally posted by mordred
The type of array is not really a key-value pair array, but OTOH it is. Sounds confusing? That's due to PHPs arrays, they always have keys and values. But generally one thinks of key-value arrays (or associative arrays) as arrays with string keys, as opposed to numerically indexed arrays.

Would it be right to think of it in terms of sequential arrays and associative arrays? The way func_get_args() interprets the agruments was confusing..."an array is not necessarily an array" it seems.



The "advanced" array features provide some kind of beauty through simplicity, if you understand what I mean here. Ok, I stop with this esoteric rambling. For now. ;)
lol, no rambling, you just gave me a 101 on "good coding practice". Theres a subtlety in good code - it takes advantages of things. To me, this is good code, and yes, it's damn beautiful to read.

Callback functions!!! Wow...i like!



EZ Archive Ads Plugin for vBulletin Copyright 2006 Computer Help Forum