...

View Full Version : Make this method recursive



cfructose
03-03-2010, 07:27 PM
I've been trying to reformulate the code of this method in order to remove the redundant duplication. I'm sure this is easily achieved, but my attempts at making this recursive are falling flat on their face.

Note that the keys 'textInput' and 'checkboxes' (shown in the multidimensional array at the end of this post) contain one level deeper, hence my problem.



function getPOST($config) {
foreach ($config['comments']['form']['visibleFields'] as $k => $v) {
if ($k != 'textInput' && $k != 'checkboxes') {
if (isset($_POST[$k])) {
$this->toPost[$k] = $_POST[$k];
}
}
else {
foreach ($config['comments']['form']['visibleFields'][$k] as $kk => $vv) {
if (isset($_POST[$kk])) {
$this->toPost[$kk] = $_POST[$kk];
}
}
}
}

return $this->toPost;
}

Any pointers most gratefully received.

BTW, the array in question is:


$config['comments']['form'] = array(
'legend' => "Got something to say...?",
'visibleFields' => array(
'textInput' => array(
'name' => array('label' => "Name", 'required' => TRUE),
'email' => array('label' => "Email", 'required' => FALSE),
'website' => array('label' => "Website (if you have one)", 'required' => FALSE)
),
'rating' => array('label' => "Rate this article", 'required' => TRUE),
'comment' => array('label' => "Comment", 'rows' => 15, 'cols' => 55),
'checkboxes' => array(
'emailFollowups' => array('label' => "Notify me of follow-up comments via email", 'checked' => FALSE),
'newsletter' => array('label' => "Subscribe to the ".$companyName." newsletter", 'checked' => FALSE)
)
),
'hiddenFields' => array(
'article_id'
),
'manual' => array(
'is_approved'
),
'autoCalculated' => array(
'ip',
'country',
'flag',
'article_name',
'date'
)
);

MattyUK
03-04-2010, 02:49 AM
Tonight I'm afraid I haven't quite the cognitive power to tread through your code (bad, tiring day). Might help if you commented it explaining it as you went, but probably not necessary for many others. Anyway I wanted to let you know I had a similar problem once with a multidimensional array. For me the solution was to test the foreach value using is_array (http://us2.php.net/manual/en/function.is-array.php) then change the part I was acting on.

if(is_array($value))
{
$blah=$value[0]['whateveritwas'];
}
elseif(is_string($value))
{
$blah=$value;
}


Just an idea. Not sure if it will fit for you.

Matt

cfructose
03-04-2010, 03:09 AM
Thanks Matty,

Yeah, unfortunately, using is_array won't work here (I thought of that already)...

The values in the multidimensional array that I need to perform a recursive foreach on are all arrays themselves. But so too are the values in the array that I DON'T need recursion on. So is_array would return TRUE for everything!

This is what I need to do. Something like the following anyway...


function getPOST(&$config) {
foreach ($config['comments']['form']['visibleFields'] as $k => $v) {
if (!is_array($v)) {//If value is NOT an array
$this->toPost[$k] = $_POST[$k]; //grab $_POST data
}
else {//If it IS an array, loop back recursively
getPOST($config);
}
}
}

But how can I do this without using is_array?

I hope that's clearer.

Thanks

MattyUK
03-04-2010, 03:32 AM
Humm so (forgive my slowness) you need to test each array and sub array for a condition and act on it if found?

If I'm in the right ballpark then would writing a single user function then using array-walk-recursive (http://www.php.net/manual/en/function.array-walk-recursive.php) work for you? I think it'd apply the custom function to each element of the array and walk recursively down into all dimensions.

If I 'get' things correctly then your custom function could contain all the custom test conditions you need maybe even contain its own single foreach but that may not be necessary since array_walk_recursive is well... recursive.

At a glance I couldn't spot why your:

else {//If it IS an array, loop back recursively
getPOST($config);
}

wouldn't work.

ooo, would you need getPOST($config) to be $this->getPOST($config)?

Sorry if I'm off base. I suspect I'm out of ideas. Perhaps after a nights sleep...

Matt

cfructose
03-04-2010, 03:54 AM
You weren't at all off base.
All great suggestions... I never thought of array_walk_recursive. (Never used it before, so unfamiliar). I'm sure it would work.

Well spotted, by the way, that I'd left off the "$this->".

OK, I've solved it.
Here's the simple solution, in case it helps anyone in future (or satisfies Matty's curiosity):



function getPOST(&$fields) {
foreach ($fields as $k => $v) {
if ($k != 'textInput' && $k != 'checkboxes') {
if (isset($_POST[$k])) {
$this->toPost[$k] = $_POST[$k];//grab $_POST data
}
}
else {
$this->getPOST($v);//loop back recursively
}
}

return $this->toPost;
}

The trick was that I shouldn't have been passing the entire $config array to the method. By passing the array only from the depth required, I solved the problem of being able to pass the array key by reference recursively without the use of 'is_array'.

Thus:


$toPost = $commentsObj->getPOST($config['comments']['form']['visibleFields']);

Instead of:



$toPost = $commentsObj->getPOST($config);

Thanks for all your help, Matty. It's funny how just the act of trying to write out a problem for others to read can help so much. I guess I ought to learn from that and write out questions without bothering to post them. I'm sure that very process would result in my finding answers for myself most of the time.

Still, your suggestions will come in handy in future. :thumbsup:

MattyUK
03-05-2010, 05:44 AM
Wonderful. Glad the ideas help.

Still post anyway, your questions may help other readers. :)



EZ Archive Ads Plugin for vBulletin Copyright 2006 Computer Help Forum