Как правильно обрабатывать переменные $ _GET в PHP? - PullRequest
7 голосов
/ 08 декабря 2010

В настоящее время у меня есть следующий код:

if(isset($_GET['mid']) && !empty($_GET['mid'])) {
    $mid = $_GET['mid'];

    if(is_numeric($mid) && $mid > 0) {
        if(isset($_GET['op']) && !empty($_GET['op'])) {
            $op = $_GET['op'];

            if($op == 'info') {
            }

            if($op == 'cast') {
            }
        }
    }
}

Но я думаю, что это слишком "сложно" с операторами if внутри операторов if и т. Д. *

Вы бы по-другому справились??Как бы вы упростили это?

[РЕДАКТИРОВАТЬ] Принято Ответ:

Хорошо, я узнал несколько мелких деталей и новых функций PHP, которых я не знализ.Я не думаю, что есть точный правильный способ сделать то, что я просил.Я явно неправильно использовал некоторые функции PHP, и я исправлю это.

Мне кажется, что подобный ввод должен быть проверен / очищен с помощью функций фильтра PHP, поэтому я отмечаю ответ Арха как принятый.

Однако для конкретного университетского проекта (который PHP-код совершенно не имеет значения) я собираюсь использовать сочетание его ответа с помощником Тату Функциональная идея.Но для другого проекта я использую его ответ с идеей Игнасио , потому что он выглядит лучше и организованнее.

Ответы [ 10 ]

11 голосов
/ 08 декабря 2010

Я бы использовал filter_input с фильтром FILTER_SANITIZE_NUMBER_FLOAT для середины. Примерно так:

$mid = filter_input(INPUT_GET, 'mid', FILTER_SANITIZE_NUMBER_FLOAT);
$op = filter_input(INPUT_GET, 'op');
if($mid > 0){
  switch($op){
    case 'info':
      // Some code
      break;
    case 'cast':
      // Some more code
      break;
    default:
      break;
  }
}
5 голосов
/ 08 декабря 2010

Я бы написал функцию, которая бы взяла имя индекса и либо вернула бы значение в пределах $_GET, либо сгенерировала бы исключение.

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

#$_GET = array('name' => 'Ignacio', 'foo' => '42');

class Get
{
  public static function string($name)
  {
    if (isset($_GET[$name]))
    {
      return $_GET[$name];
    }
    else
    {
      throw new Exception(sprintf('Unknown GET parameter "%s"', $name));
    }
  }

  public static function int($name)
  {
    $val = Get::string($name);
    $ret = filter_var($val, FILTER_VALIDATE_INT);
    if ($ret != $val)
    {
      throw new Exception(sprintf('Invalid int GET parameter "%s"', $name));
    }
    return $ret;
  }
}

echo Get::string('name') . "\n";
echo Get::int('foo') . "\n";
#echo Get::int('name') . "\n";
#echo Get::int('age') . "\n";
4 голосов
/ 08 декабря 2010
  1. empty уже проверяет, является ли переменная isset.
  2. is_numeric немного многословно, так как вы также проверяете по 0.
  3. Оператор switch лучше всего подходит для проверки переменных по нескольким строковым значениям

Я бы сделал это:

$mid = empty($_GET['mid']) ? 0 : (int)$_GET['mid'];
                                 // casting as an integer will
                                 // make undesirable strings = 0

if ($mid > 0 && !empty($_GET['op'])) {
    switch($_GET['op']) {
        case 'info':
            break;
        case 'cast':
            break;
        default:
            break;
    }
}

Если вам нужно сохранить $_GET['op'] в переменной для дальнейшего использования, вы можете сделать это до блока переключателей, хотя я бы этого не сделал, если только это не было необходимо.

3 голосов
/ 08 декабря 2010

Мне нравится идея создания класса InputFilter, который реализует ArrayAccess. Это больше объектно-ориентированный и более настраиваемый, так как вы можете добавлять методы по своему усмотрению для настройки и работать с тем же основным фильтрующим объектом.

$get = new InputFilter($_GET);
echo $get->value_integer('variable_name');

Что приятно и в этом, так это то, что его можно использовать повторно за $ _POST и т. Д. Вам просто нужно сделать что-то вроде $post = new InputFilter($_POST);. И вы можете использовать его и для других источников ввода.

Или, если у вас достаточно новая версия php, вы можете также реализовать filter_input () позже, как это предложено @Arkh. ИМО, ваш собственный класс кажется намного более пригодным для повторного использования и долговечным.

<?php

// empty for now, fill in later if desired
class InputFilterException extends Exception {}

/*
 * Use the ArrayAccess interface as a template.
 *
 * Usage examples:
 *    $controller->get = InputFilter($_GET);
 *    echo $controller->get->value_string_html('variable');
 *    $controller->post = InputFilter($_POST);
 *    echo $controller->get->value_integer('variable');
 */
class InputFilter implements ArrayAccess {

    protected $data;

    function __construct( $data ) {
        if( !is_array($data) ) {
            throw new InputFilterException ("Only arrays are allowed here");
        }
        $this->data = $data;
    }

    // do not actually use these
    function __get( $offset ) {
        throw new InputFilterException( "Don't use as an array, use functions ->string() ->int() etc: ['" . $offset . "']" );
    }
    function __set( $offset, $value ) {
        throw new InputFilterException( "Don't modify directly: ['" . $offset . "'] = \"" . $value . "\"" );
    }

    // implement ArrayAccess

    function offsetExists( $offset ) {
        return isset( $this->data[$offset]) );
    }

    function offsetSet( $offset, $value ) {
        $this->data[$offset] = $value;
    }

    function offsetUnset( $offset ) {
        unset( $this->data[$offset] );
    }

    function offsetGet( $offset ) {
        throw new InputFilterException ("Don't use this object as an array, but were an array : ". $offset);
    }

    protected function getValue( $offset ) {

        if( is_array($this->data[$offset]) ) {
            throw new InputFilterException ("must use the asArray() function");
        }
        return $this->data[$offset];
    }

    function data_count() {
        return count($this->data);
    }

    public function set_value( $offset, $data ) {
        $this->offsetSet( $offset, $data );
    }

    // get an array *in* the data
    public function asArray($offset) {

        if( !is_array ($this->data[$offset]) ) {
            throw new InputFilterException("only use asArray() for arrays");
        }
        return new Filter( $this->data[$offset] );
    }

    // validators...

    function is_set( $offset ) {
        return $this->offsetExists($offset);
    }

    function is_empty( $offset ) {
        return $this->is_set($offset) && strlen($this->data[$offset]) == 0;
    }

    function is_numeric( $offset ) {
        return $this->is_set($offset) && is_numeric($this->data[$offset]);
    }

    function is_integer( $offset ) {

        if( !$this->is_set($offset) ) {
            return false;
        } elseif( is_numeric($this->data[$offset]) ) {
            $int_value = intval($this->data[$offset]);
            return $int_value == $this->data[$offset];
        } elseif( strlen($this->data[$offset]) == 0 ) {
            return true;
        }
        return false;
    }

    function is_array( $offset ) {
        return $this->is_set($offset) && is_array($this->data[$offset]);
    }

    // return data formatted

    function value_string( $offset ) {
        return $this->getValue($offset);
    }

    function value_string_html( $offset ) {
        return htmlentities( $this->getValue($offset), null, 'UTF-8' );
    }

    function value_integer( $offset ) {
        return intval( trim($this->getValue ($offset)) );
    }

    function value_numeric( $offset ) {
        return doubleval($this->getValue ($offset));
    }

    function value_alphanumeric( $offset ) {
        return preg_replace("*[^A-Za-z0-9]*", "", $this->getValue ($offset));
    }

    function value_unfiltered( $offset ) {
        return $this->getValue( $offset );
    }

}

?>
2 голосов
/ 08 декабря 2010

Что вы можете сделать, это определить функцию фильтра (которая уже существует в PHP> = 5.2), которая будет фильтровать переменную на основе аргумента того, какой это тип, будь то число, строка или более, в зависимости отваши требования.

function myfilter($variable, $type) {
    switch($type){
        case 'numeric':
        //check for numbers
        return the number or false based on check
        break;
        case 'alphanumberic':
        //check for alphanumeric
        return the text or false based on check
        break;
    }
}

Затем используйте эту функцию для фильтрации значений, которые вы получаете, используя $ _GET

$foo = myfilter($_GET['foo'], 'numeric');
$bar = myfilter($_GET['bar'], 'alphanumeric');
2 голосов
/ 08 декабря 2010

Вы могли бы сделать вспомогательную функцию:

function getvar($var) {
    return isset($_GET[$var]) && !empty($_GET[$var]) ? $_GET[$var] : false;
}

$mid = getvar('mid');
$op = getvar('op');

if(is_numeric($mid) && $mid > 0) {
    if($op == 'info') {
    }

    if($op == 'cast') {
    }
}

Это сделало бы ваш код немного чище, но с самим кодом все в порядке.

0 голосов
/ 10 декабря 2014

Мне нравится следующий подход для целочисленных переменных:

private function _extract_int_val($val) {
    if ( isset($val) ) {
        $number = esc_sql($val);
        if ( is_numeric($number) && $number >= 0) {
            return (int) $number;
        }
    }
}
0 голосов
/ 08 декабря 2010

Это выглядит немного сложным.Но, похоже, вы хотите проверить очень много краевых условий.Однако есть способы унифицировать процесс.Для этого я использую класс-оболочку :

if ($_GET->int["mid"]) {
if ($_GET->in_array("op", "info,cast")) {

Но можно определить собственный метод, который объединяет все isset и is_numeric или любые другие проверки.

0 голосов
/ 08 декабря 2010

Я бы сделал что-то вроде ниже.Более менее.Но вы также можете использовать фильтр для многих из этих вещей.И вы также можете отключить предупреждения и просто использовать empty () и не беспокоиться об isset в первом блоке.

function checkVar($var)
{
    if(isset($var) && !empty($var)) {
        return true;
    }
    return false;
}

function checkID($id){
    if(checkVar($id) && is_numeric($id) && $id > 0) {
        return $id;
    }
    return false; 
}

if($mid = checkID($_GET['mid'])) {
    if(checkVar($_GET['op'])) {
        switch($_GET['op']) {
            case 'info':
            break;

            case 'cast':
            break;
        }
    }
}
0 голосов
/ 08 декабря 2010

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

...