Перевірте, чи існує var перед тим, як скасувати налаштування в PHP?


88

Якщо ви повідомляєте про помилки або навіть найкращу практику, коли знімаєте значення змінної в PHP, чи слід перевіряти, чи існує вона спочатку (у цьому випадку вона не завжди існує), і скасувати її, або просто зняти?

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

// OR

unset($_SESSION['signup_errors']);
?>


1
Це ефективніше у NOTвикористанні isset. Погляньте на мою відповідь. Я провів тести, щоб знайти різницю швидкості.
Ден Брей

Відповіді:


167

Просто зніміть його, якщо він не існує, нічого не буде зроблено.


3
Я не знав, чи це викличе попередження чи повідомлення
JasonDavis

19
@SilentGhost Я згоден, здається, такий простий тест, але вони просять професійної консультації, і хоча журнал помилок може не мати помилок / попереджень / сповіщень про зняття невизначеної змінної, могли бути й інші проблеми, які не реєструвались. наприклад, просто виклик unset означає, що PHP перебирає ВСІ дані var, оскільки він не може нічого знайти, тоді як використання if setможе мати кращу схему індексації. (Тільки приклад, попередній - це, мабуть, швець, і обидва підходи використовують однаковий метод перевірки даних).
Джеймс

Правда, і це також ефективніше. Погляньте на мою відповідь, тому що я перевірив швидкість використання issetневірних віршів isset.
Dan Bray

голосувати проти - ви не можете скасувати ключі масиву, які не визначені.
Бехнам

1
@jascha Я сказав, ми не можемо!
Бехнам,

48

З Посібника PHP :

Що стосується певної плутанини в цих примітках раніше про те, що змушує unset () спрацьовувати сповіщення при знятті неіснуючих змінних ....

Видалення змінних, які не існують, як у

<?php
unset($undefinedVariable);
?>

не викликає повідомлення "Невизначена змінна". Але

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

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


41
Це потребує трохи більше роз’яснень. Ви можете скасувати ключі масиву, які не визначені, доки існує сам масив.
kingmaple

@kristovaher Дійсно - це взагалі не стосується конкретного сценарію, який описує OP.
Mark Amery

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
    • Невизначено без осінь
  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);
}

Маючи справу з предметами, слід подумати про інше, і це видимість.

Те, що воно існує, не означає, що у вас є дозвіл його змінювати.


Нарешті, правильна відповідь. Дякую.
wp78de

Невелике оновлення: У PHP 7.4 / 8.0 не виникає помилка, коли ви маєте unsetвластивість неіснуючого батьківського об'єкта. Однак зняття ключа з неіснуючого масиву в PHP8 викликає не тільки сповіщення, але і попередження (може бути змінено).
wp78de

1

Перевірте це посилання https://3v4l.org/hPAto

Інтернет-інструмент показує сумісність коду для різних версій PHP

Відповідно до цього інструменту код

unset($_SESSION['signup_errors']);

буде працювати для PHP> = 5.4.0, не даючи вам жодних повідомлень / попереджень / помилок.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.