Должен ли я объявлять и проверять, существуют ли переменные в PHP?

Я заметил на XAMPP, что строгая отчетность об ошибках включена, и теперь я получаю ошибки индекса undefined. У меня только два небольших вопроса (я все еще изучаю здесь):

Я знаю, что вам не нужно объявлять переменные в PHP, но есть ли какие-либо преимущества для их объявления? Если нет, то почему я получаю ошибки, когда строгая отчетность об ошибках включена, когда я их не определяю?

Когда я использую переменные get, например, я проверяю их значение, прежде чем запускать функцию типа

if($_GET['todo'] == 'adduser')
    runFunctionAddUser();

Это дает ошибку, потому что я никогда не проверяю, существует ли первая переменная get. Должен ли я делать

if(isset($_GET['todo']))
    if($_GET['todo'] == 'adduser')
        runFunctionAddUser();

вместо этого? Было бы преимуществом для этого или было бы ненужным и медленным?

Ответ 1

Этот поток abit old, но я сделал несколько тестов, связанных с вопросом, поэтому я мог бы также опубликовать его:

Код тестирования (PHP 5.3.3 - выпуск CentOS 6.5 (Final)):

class NonExistant
{
    protected $associativeArray = array(
        'one' => 'one',
        'two' => 'two',
        'three' => 'three',
        'four' => 'four',
        'five' => 'five',
        'six' => 'six',
    );

    protected $numIterations = 10000;

    public function noCheckingTest()
    {
        for ($i = 0; $i < $this->numIterations; $i++) {
            $this->associativeArray['none'];
        }
    }

    public function emptyTest()
    {
        for ($i = 0; $i < $this->numIterations; $i++) {
            empty($this->associativeArray['none']);
        }
    }

    public function isnullTest()
    {
        for ($i = 0; $i < $this->numIterations; $i++) {
            is_null($this->associativeArray['none']);
        }
    }


    public function issetTest()
    {
        for ($i = 0; $i < $this->numIterations; $i++) {
            isset($this->associativeArray['none']);
        }
    }

    public function arrayKeyExistsTest()
    {
        for ($i = 0; $i < $this->numIterations; $i++) {
            array_key_exists($this->associativeArray['none']);
        }
    }
}

Результаты:

| Method Name                              | Run time             | Difference
=========================================================================================
| NonExistant::noCheckingTest()            | 0.86004090309143     | +18491.315775911%
| NonExistant::emptyTest()                 | 0.0046701431274414   | +0.95346080503016%
| NonExistant::isnullTest()                | 0.88424181938171     | +19014.461681183%
| NonExistant::issetTest()                 | 0.0046260356903076   | Fastest
| NonExistant::arrayKeyExistsTest()        | 1.9001779556274      | +209.73055713%

Все функции называются одинаково с помощью call_user_func() и синхронизируются с microtime(true)

Наблюдения

empty() и isset() являются явными победителями других двух методов, эти два метода в значительной степени связаны с производительностью.

is_null() работает плохо, потому что сначала нужно искать значение, почти такое же, как просто доступ к несуществующему значению $this->associativeArray['none'], что предполагает полный поиск массива.

Однако меня удивляет производительность array_key_exists(). Где он в 2 раза медленнее, чем empty() и isset().

Примечание:

Все те функции, которые я тестировал, имеют разные применения, этот критерий доступен только для наиболее распространенного варианта использования, когда вы хотите быстро проверить значение в массиве. Мы можем рассуждать о том, следует ли считать null "значением" или просто индикатором несуществования, но это другая тема. o.o

ОБНОВЛЕНИЕ 2017-01-20

Использовать PHP 7.1

Исправлена ​​ошибка, отмеченная @bstoney

$ php -v
PHP 7.1.0 (cli) (built: Dec  2 2016 03:30:24) ( NTS )
Copyright (c) 1997-2016 The PHP Group
Zend Engine v3.1.0-dev, Copyright (c) 1998-2016 Zend Technologies
$ php -a
php > $a = ['one' => 1, 'two' => 2, 'three' => 3];
php > $numIterations = 1000000;
php > $start = microtime(true); for ($i = 0; $i < $numIterations; $i++) { $a['none']; }; echo microtime(true) - $start;
0.43768811225891
php > $start = microtime(true); for ($i = 0; $i < $numIterations; $i++) { empty($a['none']); }; echo microtime(true) - $start;
0.033049821853638
php > $start = microtime(true); for ($i = 0; $i < $numIterations; $i++) { is_null($a['none']); }; echo microtime(true) - $start;
0.43995404243469
php > $start = microtime(true); for ($i = 0; $i < $numIterations; $i++) { isset($a['none']); }; echo microtime(true) - $start;
0.027907848358154
php > $start = microtime(true); for ($i = 0; $i < $numIterations; $i++) { array_key_exists('none', $a); }; echo microtime(true) - $start;
0.049405097961426

Ответ 2

Я бы предложил if(!empty($_GET['todo']) && $_GET['todo'] == 'adduser'). Это работает, потому что PHP коротких замыканий логических выражений.

Лучше всего разрабатывать, используя уровень сообщений об ошибках E_ALL (который включает E_NOTICE), потому что он быстро помогает определить ошибочные имена переменных/ключей.

Если вы спрашиваете, медленно ли тестируется наличие переменной, вы задаете неправильный вопрос (ответ заключается в том, что он быстро вспыхивает. Ваша медлительность работает с файловой системой/базой данных/и т.д.)..

Ответ 3

Это не ошибка в отношении отсутствующей переменной, которую вы получаете, это ошибка в попытке сравнить переменные с несуществующей переменной.

Если вы попытаетесь сравнить nothingness с 'adduser', он выдает ошибку, потому что вы не можете сравнить nothingness.

Это ответ на # 1.

Для # 2 вы ДОЛЖНЫ почти всегда (если не всегда) проверять наличие ваших переменных, особенно ваших переменных GET, потому что они настолько неустойчивы.

Ответ 4

Это не прямой ответ, потому что вы уже получили это, но информацию о том, как его заархивировать:

Я всегда использую функцию this во всех моих программах для инициализации входящих переменных (при необходимости по умолчанию).

Итак, вы можете сделать свою инициализацию следующим образом:

$todo = initGet('todo');

А затем просто проверьте нормально:

if($todo=='adduser') {

И функция:

function initGet($var, $default=''){
    if(!isset($_GET[$var])) return $default;
    return $_GET[$var];
}