Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Converting large associative arrays into local variables, based on key

Tags:

arrays

oop

php

One thing I find myself often wanting to do is convert a large associative array, usually from a POST request (a registration form, for example, with many inputs) into local variables based on the key from the array. If you are using the values from the array often, your code quickly becomes littered with long variable names and quotes.

To prevent this for small associative arrays, it is acceptable to just do something like this:

$username = $_POST['username'];
$password = $_POST['password'];

I'm not escaping them for this example to keep everything as uncluttered as possible, so relax.

You can also do this:

list($username, $password) = $_POST;

But what if the $_POST array is larger? Then it becomes tedious to do both of those methods. To fix that, you can run a loop like this:

foreach($arr as $key => $value)
{
    ${$key} = $value;
}

The problem with this method is that it assigns local variables. It would be nice if it were possible to call a function in a parent class that runs this loop and those local variables were accessible within the calling class. Imagine an MVC setup where every controller is derived from a Controller class, and likewise for the models. It would be nice to do:

$this->localize($_POST);
doWhatever($username) // $username works! Assuming $_POST['username'] is defined

Creating such a method causes the local variables to only remain within the scope of the localize() function in the parent class, so this won't work. What I have been doing is running the same loop with one modification:

foreach($arr as $key => $value)
{
    $this->{$key} = $value;
}

This works and all, but doesn't really solve the initial problem. Instead of code that is cluttered with brackets and quotes, it has $this-> all over the place, not to mention it is assigning variables that were never formally defined within the class.

So finally, my question: is it possible to create a function such as the localize() I described, such that it can be inherited from a parent class but create local variables relative to the child class ($username instead of $this->username).

Also, whether you can or not, is this considered bad practice? It seems a bit hacky to me, and you are ignoring some principles of OOP. If it is, do you use a solution to fix the ugliness and clutter of large associative arrays, or do you just deal with it?

like image 796
Logan Serman Avatar asked Apr 01 '12 23:04

Logan Serman


2 Answers

The PHP extract function does exactly this. Extracts a hash into the local namespace:

http://us3.php.net/extract

An important addendum:

Be sure to use the EXTR_SKIP option for extract() if the function is acting on user-supplied variable names (such as provided by $_POST) to prevent redefining of existing variables:

$myvar = 'abc';
extract($_POST, EXTR_SKIP);  // $_POST['myvar'] won't overwrite $myvar.
like image 177
leepowers Avatar answered Nov 14 '22 07:11

leepowers


It's a bad practice, users will be able to redefine any of your variables just by passing key in POST array, it's pretty simple and it's how register_globals works, and it's why this ability is deprecated in 5.3 and removed in 5.4.

like image 21
OZ_ Avatar answered Nov 14 '22 08:11

OZ_