В моем коде я хочу попробовать получить переменные $ _POST или $ _GET и отключить их, как только они будут запрошены один раз.

Эта функция возвращает используемый метод, что достаточно просто. К сожалению, я не могу просто вернуть переменные $ _POST или $ _GET напрямую или по ссылке, потому что я не смогу их отключить (отключение по ссылке не работает). Итак, я возвращаю имена переменных:

class Input {
  protected function interface_get($method): string {
    switch ($method) {
      case 'post':
        return '_POST';
        break;
      case 'get':
        return '_GET';
        break;
      case 'ajax':
        // Not supported yet.
        return null;
        break;
      default:
        return null; // returns '_GET' or '_POST'
    }
  }
  public function fetch_eval(string $method, ?string $request = null) { // ...fetch('post', 'username')
    if ($request !== null) {
      $request = '[\'' . $request . '\']'; // "['username']"
    }
    $request = $this->interface_get($method) . $request; #"$_POST['username']"
    eval('$return = $' . $request . ';'); #$return = $_POST['username'];
    eval('unset($' . $request . ');'); #unset($_POST['username']);
    return $return;
  }
  public function fetch_varvar(string $method, ?string $request = null) {
    $interface = $this->interface_get($method); #$interface = '_POST';
    if ($request === null) {
      $return = (${$interface});
      unset(${$interface});
    } else {
      $return = ${$interface}; #"Notice:  Undefined variable: _POST in [...]"
      $return = ${$interface}[$request]; #"Warning:  Illegal string offset 'email' in [...]"
      unset($interface[$request]);
    }
    return $result;
}
}
// set $_POST = ['email'=>'spam@me'];
$in = new Input();
echo $in->fetch_eval('post', 'email'); #'spam@me'
// $_POST = [];

// set $_POST = ['email'=>'spam@me']; again
echo $in->fetch_varvar('post', 'email'); #'Notice:  Undefined variable: _POST [...]'

Самое интересное - это обработка этого вывода. Вот моя функция выборки, самый простой, но, на мой взгляд, самый грязный способ:

Я пробовал использовать переменные переменные, в тестовом скрипте это сработало:

// $_POST = [0 => 5, 'bob' => 5];
$e = '_POST';
$var = 'bob';
echo ${$e}[$var]; #5
unset(${$e}[$var]);
echo ${$e}[$var ]; #NOTICE Undefined index: bob on line number 22
// Works as expected.

Но в моем скрипте (Undefined variable: _POST [...].) Это не сработало. Я подумал, может быть, причина в том, что это было в классе, но все равно я не мог ее решить. Более того, если вы поместите эти функции вне класса и удалите $this-> - ы, они будут работать! Но не внутри класса.

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

Я хотел бы сохранить interface_get() как отдельную функцию, но, если нужно, я могу продублировать ее и внутри fetch(), я полагаю.

Заранее большое спасибо.

3
Dwarf Vader 14 Мар 2018 в 01:47

2 ответа

Лучший ответ

Вы можете использовать $GLOBALS[$interface] для получения данных.

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

public function fetch(string $method, ?string $request = null) {
    $interface = $this->interface_get($method); #$interface = '_POST';
    if ($request === null) {
        $result = $GLOBALS[$interface];
        unset($GLOBALS[$interface]);
        return $result;
    }
    if (isset($GLOBALS[$interface][$request])) {
        $result = $GLOBALS[$interface][$request];
        unset($GLOBALS[$interface][$request]);
        return $result;
    }
    return null;
}
1
Syscall 14 Мар 2018 в 10:57

@Syscall и @Ignacio Vazquez-Abrams ответили на этот вопрос в комментариях.

Согласно документации PHP (https://php.net/manual/en/language .variables.superglobals.php):

Суперглобальные объекты нельзя использовать в качестве переменных переменных внутри функций или методов класса.

Вот почему он не работал внутри класса Input. Чтобы это сработало, мне пришлось использовать переменную $ GLOBALS вот так:

public function fetch(string $method, ?string $request = null) {
    $interface = $this->interface_get($method); #$interface = '_POST';
    if ($request === null) {
        $return = $GLOBALS[$interface];
        unset($GLOBALS[$interface]);
    } else {
        $return = $GLOBALS[$interface][$request];
        unset($GLOBALS[$interface][$request]);
    }
    return $return;
}

Этот код работал. Большое спасибо за ваш вклад. Может быть лучший или более элегантный способ добиться того, что я искал. В этом случае всегда приветствуется дальнейший вклад.

1
Dwarf Vader 14 Мар 2018 в 14:33