Как избежать isset () и пустой()



у меня есть несколько старых приложений, которые бросают много сообщений" xyz is undefined "и" undefined offset " при запуске на уровне ошибок E_NOTICE, потому что существование переменных явно не проверяется с помощью isset() и наложницы.



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



однако мне не нравится то, что причиняет сотни isset()empty() и array_key_exists() s делает с моим кодом. Он раздувается, становится менее читаемым, не приобретая ничего с точки зрения ценности или смысла.



как я могу структурировать свой код без избытка проверок переменных, а также быть совместимым с E_NOTICE?

632   11  

11 ответов:

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


IMHO вы должны думать не только о том, чтобы сделать приложение "E_NOTICE совместимым", но и о реструктуризации всего этого. Имея сотни из точек в вашем коде, которые регулярно пытаются использовать несуществующие переменные, звучит довольно плохо структурированная программа. Попытка доступа к несуществующим переменным никогда не должна происходить, другие языки отказываются от этого во время компиляции. Тот факт, что PHP позволяет вам это делать, не означает, что вы должны.

эти предупреждения существуют для помогите ты, чтобы не раздражать тебя. Если вы получите предупреждение

просто напишите функцию для этого. Что-то вроде:

function get_string($array, $index, $default = null) {
    if (isset($array[$index]) && strlen($value = trim($array[$index])) > 0) {
        return get_magic_quotes_gpc() ? stripslashes($value) : $value;
    } else {
        return $default;
    }
}

который вы можете использовать как

$username = get_string($_POST, 'username');

сделайте то же самое для тривиальных вещей, таких как get_number(),get_boolean(),get_array() и так далее.

Я считаю, что одним из лучших способов справиться с этой проблемой является доступ к значениям GET и POST (COOKIE, SESSION и т. д.) массивов через класс.

создать класс для каждого из этих массивов и объявить __get и __set методы (перегрузка). __get принимает один аргумент, который будет называться значение. Этот метод должен проверить это значение в соответствующем глобальном массиве либо с помощью isset() или empty() и возвращает значение, если оно существует или null (или другое значение по умолчанию), в противном случае.

после этого вы можете уверенно получить доступ к значениям массива таким образом: $POST->username и сделать любую проверку, если это необходимо без использования каких-либо isset()или empty() s. Если username не существует в соответствующем глобальном массиве null будет возвращен, поэтому никаких предупреждений или уведомлений не будет создано.

Я не против использовать array_key_exists(), на самом деле я предпочитаю использовать эта специфическая функция вместо того, чтобы полагаться на hack функции, которые могут изменить их поведение в будущем как empty и isset (зачеркнуто, чтобы избежать эффекты).


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

function Value($array, $key, $default = false)
{
    if (is_array($array) === true)
    {
        settype($key, 'array');

        foreach ($key as $value)
        {
            if (array_key_exists($value, $array) === false)
            {
                return $default;
            }

            $array = $array[$value];
        }

        return $array;
    }

    return $default;
}

допустим, у вас есть следующие массивы:

$arr1 = array
(
    'xyz' => 'value'
);

$arr2 = array
(
    'x' => array
    (
        'y' => array
        (
            'z' => 'value',
        ),
    ),
);

как вы получаете "значение" из массивов? Просто:

Value($arr1, 'xyz', 'returns this if the index does not exist');
Value($arr2, array('x', 'y', 'z'), 'returns this if the index does not exist');

у нас уже есть Uni и многомерные массивы покрыты, что еще мы можем сделать?


Возьмите следующий фрагмент кода, например:

$url = 'https://stackoverflow.com/questions/1960509';
$domain = parse_url($url);

if (is_array($domain) === true)
{
    if (array_key_exists('host', $domain) === true)
    {
        $domain = $domain['host'];
    }

    else
    {
        $domain = 'N/A';
    }
}

else
{
    $domain = 'N/A';
}

довольно скучно не так ли? Вот еще один подход с использованием Value() функция:

$url = 'https://stackoverflow.com/questions/1960509';
$domain = Value(parse_url($url), 'host', 'N/A');

так, например, взять RealIP() функции для теста:

$ip = Value($_SERVER, 'HTTP_CLIENT_IP', Value($_SERVER, 'HTTP_X_FORWARDED_FOR', Value($_SERVER, 'REMOTE_ADDR')));

прикольно, да? ;)

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

Я использую эти функции

function load(&$var) { return isset($var) ? $var : null; }
function POST($var) { return isset($_POST[$var]) ? $_POST[$var] : null; }

примеры

$y = load($x); // null, no notice

// this attitude is both readable and comfortable
if($login=POST("login")) // really =, not ==
if($pass=POST("pass"))
if($login=="Admin" && $pass==...) {
  // login and pass are not empty, login is "Admin" and pass is ...
  $authorized = true;
  ...
}

сделать функцию, которая возвращает значение false если не установлено, и, если указано, false если пустой. Если он действителен, он возвращает переменную. Вы можете добавить дополнительные параметры, как показано в коде ниже:

<?php
function isset_globals($method, $name, $option = "") {
    if (isset($method[$name])) {    // Check if such a variable
        if ($option === "empty" && empty($method[$name])) { return false; } // Check if empty 
        if ($option === "stringLength" && strlen($method[$name])) { return strlen($method[$name]); }    // Check length of string -- used when checking length of textareas
        return ($method[$name]);
    } else { return false; }
}

if (!isset_globals("$_post", "input_name", "empty")) {
    echo "invalid";
} else {
    /* You are safe to access the variable without worrying about errors! */
    echo "you uploaded: " . $_POST["input_name"];
}
?>

Добро пожаловать в Оператор слияния Null:

$field = $_GET['field'] ?? null;

в PHP говорит:

оператор коалесценции null (??) был добавлен в качестве синтаксического сахара для общего случая необходимости использования тернарного в сочетании с isset (). Он возвращает первый операнд, если он существует и не равен NULL; в противном случае возвращается второй операнд.

Я не уверен, что ваше определение читаемости, но правильное использование пустых (), isset() и try/throw/catch блоков, довольно важно для всего процесса. Если ваш E_NOTICE поступает из $_GET или $_POST, то они должны быть проверены на пустом() прямо вместе со всеми другими проверками безопасности, которые должны пройти эти данные. Если он поступает из внешних каналов или библиотек, он должен быть завернут в try/catch. Если он поступает из базы данных, $db_num_rows() или это эквивалентно надо проверить. Если он исходит от внутренних переменных, они должны быть правильно инициализированы. Часто эти типы уведомлений приходят из назначения новой переменной для возврата функции, которая возвращает FALSE при сбое, они должны быть завернуты в тест, который в случае сбоя может либо назначить переменной приемлемое значение по умолчанию, которое может обрабатывать код, либо создать исключение, которое может обрабатывать код. Эти вещи делают код длиннее, добавляют дополнительные блоки и добавляют дополнительные тесты, но я не согласен с вами в том, что я думаю, что они определенно добавляют дополнительную ценность.

программа не может выполняться по благодати Божьей, если вы ожидаете, что нужно правильно обращаться. если вы игнорируете его, вы, вероятно, создаете дыры в безопасности в своих приложениях. на статических языках доступ к неопределенной переменной просто невозможен, он не будет просто компилировать или аварийно завершать работу вашего приложения, если он равен null. кроме того, делает ваше приложение недостижимым, и вы собираетесь сойти с ума, когда происходят неожиданные вещи. строгость языка must и php, по дизайну, ошибочны во многих аспектах. это сделает вас плохим программистом, если вы не знаете.

Как насчет использования оператора@? например:

if(@$foo) { /* do something */ }

вы можете сказать, что это плохо, потому что у вас нет контроля над тем, что происходит "внутри" $foo (если это был вызов функции, который содержит ошибку PHP, например), но если вы используете этот метод только для переменных, это эквивалентно:

if(isset($foo) && $foo) { /* ... */ }

Comments

    Ничего не найдено.