Проверить, существует ли var перед отключением в PHP?

88

С сообщением об ошибках или даже для лучшей практики при отключении переменной в PHP, следует ли вам сначала проверить, существует ли она (в этом случае она не всегда существует), и отключить ее, или просто отключить ее?

<?PHP
if (isset($_SESSION['signup_errors'])){
    unset($_SESSION['signup_errors']);
}

// OR

unset($_SESSION['signup_errors']);
?>
ДжейсонДэвис
источник
2
Ср. dk2.php.net/unset#77310
jensgram 03
1
Это более эффективно в NOTиспользовании isset. Посмотри на мой ответ. Я сделал тесты, чтобы найти разницу в скорости.
Дэн Брэй

Ответы:

167

Просто отключите его, если его нет, ничего не будет сделано.

Жоао Силва
источник
3
Я не знал, будет ли это предупреждение или уведомление,
Джейсон Дэвис,
19
@SilentGhost Я согласен, это кажется таким простым тестом, но они просят профессионального совета, и хотя в журнале ошибок может не быть никаких ошибок / предупреждений / уведомлений, сбрасывающих неопределенную переменную, могли быть другие проблемы, которые не регистрируются. например, просто вызов unset означает, что PHP просматривает ВСЕ данные var, потому что он ничего не может найти, тогда как использование if setможет иметь лучшую схему индексации. (Просто пример, предыдущий, вероятно, сапожники, и оба подхода используют один и тот же метод проверки данных).
Джеймс
Верно, и это тоже более эффективно. Взгляните на мой ответ, потому что я проверил скорость использования issetстихов, которые не используются isset.
Дэн Брэй
проголосовать против - нельзя сбросить ключи массива, которые не определены.
Behnam
1
@jascha Я сказал, мы не можем!
Behnam
48

Из Руководства по PHP :

Что касается некоторой путаницы ранее в этих заметках о том, что заставляет unset () запускать уведомления при отмене переменных, которые не существуют ...

Удаление несуществующих переменных, как в

<?php
unset($undefinedVariable);
?>

не вызывает уведомление «Неопределенная переменная». Но

<?php
unset($undefinedArray[$undefinedKey]);
?>

вызывает два уведомления, потому что этот код предназначен для отмены установки элемента массива; ни $ undefinedArray, ни $ undefinedKey сами по себе не сбрасываются, они просто используются для определения того, что должно быть отключено. В конце концов, если бы они действительно существовали, вы все равно ожидали бы, что они оба появятся после этого. Вы НЕ хотите, чтобы весь ваш массив исчез только потому, что вы unset () один из его элементов!

Г-н Смит
источник
41
Это требует дополнительных разъяснений. Вы можете отключить ключи массива, которые не определены, пока существует сам массив.
kingmaple
@kristovaher Действительно - это вообще не касается конкретного сценария, описанного OP.
Марк Эмери
21

Использование unsetнеопределенной переменной не вызовет никаких ошибок (если переменная не является индексом массива (или объекта), который не существует).

Поэтому единственное, что вам нужно учитывать, - это то, что является наиболее эффективным. Как покажет мой тест, более эффективно не тестировать с помощью isset.

Контрольная работа:

function A()
{
    for ($i = 0; $i < 10000000; $i++)
    {
        $defined = 1;
        unset($defined);
    }
}

function B()
{
    for ($i = 0; $i < 10000000; $i++)
    {
        $defined = 1;
        unset($undefined);
    }
}

function C()
{
    for ($i = 0; $i < 10000000; $i++)
    {
        $defined = 1;
        if (isset($defined))
            unset($defined);
    }
}

function D()
{
    for ($i = 0; $i < 10000000; $i++)
    {
        $defined = 1;
        if (isset($undefined))
            unset($undefined);
    }
}

$time_pre = microtime(true);
A();
$time_post = microtime(true);
$exec_time = $time_post - $time_pre;
echo "Function A time = $exec_time ";

$time_pre = microtime(true);
B();
$time_post = microtime(true);
$exec_time = $time_post - $time_pre;
echo "Function B time = $exec_time ";

$time_pre = microtime(true);
C();
$time_post = microtime(true);
$exec_time = $time_post - $time_pre;
echo "Function C time = $exec_time ";

$time_pre = microtime(true);
D();
$time_post = microtime(true);
$exec_time = $time_post - $time_pre;
echo "Function D time = $exec_time";
exit();

Полученные результаты:

  1. Function A time = 1.0307259559631
    • Определено без isset
  2. Function B time = 0.72514510154724
    • Не определено без isset
  3. Function C time = 1.3804969787598
    • Определяется с помощью isset
  4. Function D time = 0.86475610733032
    • Не определено с использованием isset

Вывод:

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

Дэн Брэй
источник
1
Это лучше, чем принятый ответ! Спасибо за проведение этих тестов.
Адам Фридман,
3

Если вы хотите отключить переменную, вы можете просто использовать unset

unset($any_variable); // bool, object, int, string etc

Проверка на его существование не имеет смысла при попытке сбросить значение переменной.

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

unset($undefined_array['undefined_element_key']); // error - Undefined variable: undefined_array

unset($undefined_object->undefined_prop_name); // error - Undefined variable: undefined_object

Это легко решить, если поместить unsetв if(isset($var)){ ... }блок.

if(isset($undefined_array)){
    unset($undefined_array['undefined_element_key']); 
}

if(isset($undefined_object)){
    unset($undefined_object->undefined_prop_name); 
}

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

if(isset($array)){
...
}

if(isset($object)){
...
}

.vs

$object->prop_name = null;
$array['element_key'] = null;

// This way elements/properties with the value of `null` can still be unset.

if(isset($array) && array_key_exists('element_key', $array)){
...
}

if(isset($object) && property_exists($object, 'prop_name')){
...
}

// or 

// This way elements/properties with `null` values wont be unset.

if(isset($array) && $array['element_key'])){
...
}

if(isset($object) && $object->prop_name)){
...
}

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

То же самое при попытке сбросить значение многомерного массива или объекта. Вы должны убедиться, что родительский ключ / имя существует.

if(isset($variable['undefined_key'])){
    unset($variable['undefined_key']['another_undefined_key']);
}

if(isset($variable->undefined_prop)){
    unset($variable->undefined_prop->another_undefined_prop);
}

Имея дело с объектами, есть еще одна вещь, о которой нужно думать, и это видимость.

Тот факт, что он существует, не означает, что у вас есть разрешение на его изменение.

TarranJones
источник
Наконец, правильный ответ. Спасибо.
wp78de,
Небольшое обновление: в PHP 7.4 / 8.0 не выдается ошибка, когда вы unsetиспользуете свойство несуществующего родительского объекта. Однако при отключении ключа в несуществующем массиве в PHP8 возникает не только уведомление, но и предупреждение (которое может быть изменено).
wp78de
1

Проверьте эту ссылку https://3v4l.org/hPAto

Онлайн-инструмент показывает совместимость кода для разных версий PHP.

Согласно этому инструменту код

unset($_SESSION['signup_errors']);

будет работать для PHP> = 5.4.0 без каких-либо уведомлений / предупреждений / ошибок.

евгписарчик
источник