Насколько важно проверять каждый индекс массива в PHP?

Я работаю над довольно большим проектом, в котором есть много мест, где существует такой код:

function foo($a, $b, $c, $d, $e, $f) {
    $clean = array();
    $mysql = array();

    $clean['a'] = htmlentities($a);
    $clean['b'] = htmlentities($b);
    $clean['c'] = htmlentities($c);
    $clean['d'] = htmlentities($d);
    //...

    $mysql['a'] = mysql_real_escape_string($clean['a']);
    $mysql['b'] = mysql_real_escape_string($clean['b']);
    $mysql['c'] = mysql_real_escape_string($clean['c']);
    $mysql['d'] = mysql_real_escape_string($clean['d']);
    //...

    //construct and execute an SQL query using the data in $mysql
    $query = "INSERT INTO a_table
              SET a='{$mysql['a']}',
                  b='{$mysql['b']}',
                  c='{$mysql['c']}',
                  d='{$mysql['d']}'";
}

Очевидно, что в PHP выдается много предупреждений для неопределенных индексов.

Действительно ли необходимо переписать код следующим образом?

function foo($a, $b, $c, $d, $e, $f) {
    $clean = array();
    $mysql = array();

    $clean['a'] = htmlentities($a);
    $clean['b'] = htmlentities($b);
    $clean['c'] = htmlentities($c);
    $clean['d'] = htmlentities($d);
    //...

    $mysql['a'] = (isset($clean['a'])) ? mysql_real_escape_string($clean['a']) : mysql_real_escape_string($a);
    $mysql['b'] = (isset($clean['b'])) ? mysql_real_escape_string($clean['b']) : mysql_real_escape_string($b);
    $mysql['c'] = (isset($clean['c'])) ? mysql_real_escape_string($clean['c']) : mysql_real_escape_string($c);
    $mysql['d'] = (isset($clean['d'])) ? mysql_real_escape_string($clean['d']) : mysql_real_escape_string($d);
    //...

    //construct and execute an SQL query using the data in $mysql
    if (isset($mysql['a']) and isset($mysql['b']) and isset($mysql['c']) and isset($mysql['d'])) {
        $query = "INSERT INTO a_table
                  SET a='{$mysql['a']}',
                      b='{$mysql['b']}',
                      c='{$mysql['c']}',
                      d='{$mysql['d']}'";
    }

}

5 ответов

Решение

Вы можете значительно упростить свою функцию, если вы используете:

function foo($a, $b, $c, $d, $e, $f) {

    $args = func_get_args();   // or build an array() manually

    $args = array_map("htmlentities", $args);
    $args = array_map("mysql_real_escape_string", $args);

    list($a, $b, $c, $d, $e, $f) = $args;

Проверка isset() в показанной позиции кажется совершенно бесполезной. Переменные уже определены.

Да, если индекс массива или переменная не существует, php выдаст предупреждение / уведомление.

Правильный способ - проверять каждую переменную перед использованием isset() функция.

Рекомендуется проверять их перед использованием.

Нужно ли вообще иметь такую ​​жестко закодированную функцию?

Я использую это:

function insert_array($table, $data) {  
    $cols = '(';
    $values = '(';
    foreach ($data as $key=>$value) { 
        $value = mysql_real_escape_string($value);
        $cols .= "$key,";  
        $values .= "'$value',";  
    }
    $cols = rtrim($cols, ',').')';
    $values = rtrim($values, ',').')';  
    $sql = "INSERT INTO $table $cols VALUES $values";
    mysql_query($sql) or die(mysql_error());
}

Затем для вставки данных независимо от их имени и столбцов используйте:

$data = array('id' => 1, 'name' => 'Bob', 'url' => 'foo.com');
insert_array('users', $data);

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

  1. В вашем примере вы можете переместить часть mys ql_real_escape_string внутрь, если вы проверяете переменные, то вы уже знаете, что они существуют.

  2. Здесь нет причин использовать массивы, вы можете хранить их в одной переменной.

  3. XSS-Protection (htmltentities (), обратите внимание, что этого недостаточно) следует сделать перед удалением данных, а не перед сохранением, как в вашем примере. Только одна причина в том, что вы будете иметь дело с вещами, которые кодируются / экранируются несколько раз. Вредоносный HTML/JS не может навредить вашей базе данных.

Если ваш проект очень большой, то неопределенные индексы могут превратиться в настоящий кошмар, особенно если они содержат данные, сгенерированные пользовательским вводом, и ОСОБЕННО в отсутствие хороших отчетов об ошибках с трассировкой стека. Это связано с тем, что, поскольку данные передаются между запросами, нет гарантии, что они были установлены в исходной точке входа, и поэтому вы в конечном итоге выполняете много избыточных проверок на наличие нулевых или пустых значений.

Возможно, вы захотите проверить, не может ли то, чего вы пытаетесь достичь, достичь лучше, превратив эту функцию в объект. Значения, которые вы представляете с помощью $a $b и $c, могут быть легко преобразованы в свойства объекта, а один метод save() может сохранить состояние в базе данных.

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

http://php.net/manual/en/control-structures.foreach.php

Я также предлагаю HTMLPurifier для вашей фильтрации XSS, так как очень часто htmlentites недостаточно, особенно для общедоступных форм, которые допускают размещение пользовательского контента в веб-приложении.

http://htmlpurifier.org/

Другие вопросы по тегам