Преобразование больших ассоциативных массивов в локальные переменные на основе ключа - PullRequest
10 голосов
/ 02 апреля 2012

Одна вещь, которую я часто хочу сделать, - это преобразование большого ассоциативного массива, обычно из запроса POST (например, регистрационной формы с большим количеством входных данных), в локальные переменные на основе ключа из массива. Если вы часто используете значения из массива, ваш код быстро наполняется длинными именами переменных и кавычками.

Чтобы предотвратить это для небольших ассоциативных массивов, допустимо просто сделать что-то вроде этого:

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

Я не убегаю от них в этом примере, чтобы все было как можно более загромождено, поэтому расслабьтесь.

Вы также можете сделать это:

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

Но что, если массив $ _POST больше? Тогда становится утомительно делать оба этих метода. Чтобы это исправить, вы можете запустить цикл следующим образом:

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

Проблема этого метода в том, что он назначает локальные переменные. Было бы хорошо, если бы можно было вызвать функцию в родительском классе, который выполняет этот цикл, и эти локальные переменные были бы доступны в вызывающем классе. Представьте себе установку MVC, в которой каждый контроллер получен из класса Controller, а также для моделей. Было бы неплохо сделать:

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

Создание такого метода приводит к тому, что локальные переменные остаются только в области действия функции localize() в родительском классе, поэтому это не будет работать. Я выполняю один и тот же цикл с одной модификацией:

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

Это работает и все, но на самом деле не решает первоначальную проблему. Вместо кода, который загроможден скобками и кавычками, он имеет $this-> повсеместно, не говоря уже о присваивании переменных, которые никогда не были формально определены в классе.

Итак, наконец, мой вопрос: возможно ли создать такую ​​функцию, как описанный мною localize(), чтобы ее можно было наследовать от родительского класса, но создавать локальные переменные относительно дочернего класса ($username вместо $this->username).

Кроме того, можете ли вы или нет, это считается плохой практикой? Мне это кажется немного хакерским, а вы игнорируете некоторые принципы ООП. Если да, то используете ли вы решение, чтобы исправить уродство и беспорядок больших ассоциативных массивов, или вы просто справляетесь с этим?

Ответы [ 2 ]

18 голосов
/ 02 апреля 2012

Функция PHP extract делает именно это.Извлекает хеш в локальное пространство имен:

http://us3.php.net/extract

Важное дополнение:

Обязательно используйте параметр EXTR_SKIP для extract(), если функциядействие на предоставленные пользователем имена переменных (например, предоставленные $_POST) для предотвращения переопределения существующих переменных:

$myvar = 'abc';
extract($_POST, EXTR_SKIP);  // $_POST['myvar'] won't overwrite $myvar.
1 голос
/ 02 апреля 2012

Это плохая практика, пользователи смогут переопределять любые ваши переменные, просто передав ключ в массив POST, это довольно просто, и именно так работает register_globals, и именно поэтому эта возможность устарела в 5.3 и удалена в 5.4.1001 *

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...