Есть ли способ динамического доступа к суперглобальному? - PullRequest
7 голосов
/ 24 августа 2010

Как веб-разработчик, я всегда использую этот подход к чему-то вроде формы входа или другой операции «сохранить» (игнорируя опасность прямого доступа к входным переменным):

if (isset($_POST['action']) && $_POST['action'] == 'login')
{
    // we're probably logging in, so let's process that here
}

Чтобы сделать это менее утомительным и соответствовать принципам СУХОЙ (вроде), я приготовил это:

function isset_and_is ($superglobal, $key, $value)
{
    $ref = '_' . strtoupper($superglobal);

    return isset($$ref[$key]) && $$ref[$key] == $value;
}

if (isset_and_is('post', 'action', 'login'))
{
    // we're probably logging in, so let's process that here
}

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

Итак, я застрял, используя это уродливое:

function isset_and_is ($superglobal, $key, $value)
{
    switch (strtoupper($superglobal))
    {
        case 'GET':     $ref =& $_GET;     break;
        case 'POST':    $ref =& $_POST;    break;
        case 'REQUEST': $ref =& $_REQUEST; break;
        default:        die('megafail');   return;
    }

    return isset($ref[$key]) && $ref[$key] == $value;
}

if (isset_and_is('post', 'action', 'login'))
{
    // we're probably logging in, so let's process that here
}

Мой вопрос: Есть ли способ динамического доступа к суперглобальным переменным, как я пытаюсь сделать во втором примере кода? Если нет, есть ли лучший / более эффективный способ выполнить то, что я делаю в третьем примере кода?


Мое решение: Благодаря Ответ Тома Хейя , вот окончательный код, с которым я собираюсь пойти:

function isset_and_is ($superglobal, $key, $value)
{
    $ref =& $GLOBALS['_' . strtoupper($superglobal)];

    return isset($ref[$key]) && $ref[$key] == $value;
}

Ответы [ 5 ]

3 голосов
/ 24 августа 2010

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

function test($var) {
    //this 
    var_dump( $GLOBALS[$var] );

    //or this
    global $$var; //this is needed even for superglobals
    var_dump($$var);
}

test('_GET');

, чтобы вы могли использовать что-то подобное в вашем случае

function isset_and_is ($superglobal, $key, $value) {
    $var = '_' . $superglobal;
    return isset($GLOBALS[$var]) && ($GLOBALS[$var][$key] == $value);
}

$is_login = isset_and_is('GET', 'action', 'login');

Или же вы можете взять переменную по ссылке и использовать isset(), например

function get_var(& $var) {
    if (isset($var)) {
        return $var;
    }
    return null;
}

//will not give you a notice if not set
$post_var = get_var($_POST['var']);

if (get_var($_GET['action']) == 'login') {
    //stuff
}
2 голосов
/ 24 августа 2010

Если вам нужно получить данные только из одного источника, используйте Том ответ .

Однако, если вы делаете это для каждой переменной, т.е. если вы всегда признаете, что данные могут поступать из двух источников, лучшая альтернатива - объединить их.

Вы могли бы использовать $_REQUEST, но я бы посоветовал вам против этого. Порядок, в котором рассматриваются данные POST и GET, php.ini настраивается и включает другие источники.

Сделайте что-то вроде:

$data = array_merge($_GET, $_POST); //POST has precedence

, а затем получите данные от $data.

1 голос
/ 24 августа 2010

Как насчет: http://www.php.net/manual/en/function.filter-input.php

function isset_and_is ($superglobal, $key, $value) {
  switch($superglobal) {
    case 'post':
      $type = INPUT_POST;
      break;
    case 'get':
      $type = INPUT_GET;
      break;
  }
  $var = filter_input($type,$key);
  if(is_null($var)) return false;
  return($var == $value);
}
0 голосов
/ 22 января 2015

В PHP оператор @ подавляет предупреждения при оценке выражения. Например, $array[$key] возвращает значение с этим ключом, если оно существует, или null, если нет, но выдает предупреждение, если ключ не существует. Добавление оператора @ для получения @$array[$key] делает его эквивалентным array_key_exists($key, $array) ? $array[$key] : null. На самом деле, isset($something) - это всего лишь еще один способ сказать @$something === null.

Так попробуйте это:

if (@$_POST['action'] === 'login')
{
    // we're probably logging in, so let's process that here
}

В моих проектах PHP используется нечто похожее на фрагмент в документации ErrorException. Это добавляет отказоустойчивую семантику, где PHP $array[$key] означает бросить ErrorException, если его там нет, а @$array[$key] означает использование null для обозначения не найденного (как SQL LEFT JOIN).

0 голосов
/ 24 августа 2010

Если $_REQUEST по умолчанию содержит содержимое $_GET и $_POST, зачем вам нужен переключатель. Вы можете напрямую использовать это и исключить $superglobal:

function isset_and_is ($key, $value)
{
    return isset($_REQUEST[$key]) && ($_REQUEST[$key] == $value);
}
...