Sprawdź, czy istnieje var przed usunięciem ustawień w PHP?

88

Przy włączonym raportowaniu błędów, a nawet dla najlepszych praktyk, podczas kasowania zmiennej w PHP, czy powinieneś najpierw sprawdzić, czy istnieje (w tym przypadku nie zawsze istnieje) i usunąć ją, czy po prostu usunąć?

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

// OR

unset($_SESSION['signup_errors']);
?>
JasonDavis
źródło
2
Por. dk2.php.net/unset#77310
jensgram
1
Jest bardziej wydajny w NOTużyciu isset. Spójrz na moją odpowiedź. Zrobiłem testy, aby znaleźć różnicę prędkości.
Dan Bray

Odpowiedzi:

167

Po prostu go rozłącz, jeśli nie istnieje, nic nie zostanie zrobione.

João Silva
źródło
3
Nie wiedziałem, czy to wyrzuci ostrzeżenie, czy zawiadomienie
JasonDavis
19
@SilentGhost Zgadzam się, wygląda na taki prosty test, ale proszą o profesjonalną poradę i chociaż dziennik błędów może nie zawierać żadnego błędu / ostrzeżenia / powiadomienia o usunięciu niezdefiniowanej zmiennej, mogły wystąpić inne problemy, które nie są rejestrowane. np. samo wywołanie unset oznacza przeglądanie przez PHP WSZYSTKICH danych var, ponieważ nie może niczego znaleźć, podczas gdy użycie if setmoże mieć lepszy schemat indeksowania. (Tylko przykład, poprzedni to prawdopodobnie szewc i oba podejścia używają tej samej metody sprawdzania danych).
James
To prawda i jest też bardziej wydajne. Spójrz na moją odpowiedź, ponieważ przetestowałem szybkość używania issetwersetów nieużywanych isset.
Dan Bray
głosuj w dół - nie można usunąć kluczy tablicy, które nie są zdefiniowane.
Behnam,
1
@jascha Powiedziałem, nie możemy!
Behnam
48

Z podręcznika PHP :

Ze względu na pewne zamieszanie we wcześniejszej części tych uwag na temat tego, co powoduje, że unset () wywołuje powiadomienia przy wyłączaniu zmiennych, które nie istnieją ...

Usuwanie zmiennych, które nie istnieją, na przykład

<?php
unset($undefinedVariable);
?>

nie wywołuje powiadomienia „Niezdefiniowana zmienna”. Ale

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

wyzwala dwa powiadomienia, ponieważ ten kod służy do rozbrojenia elementu tablicy; ani $ undefinedArray, ani $ undefinedKey same nie są nieustawione, służą jedynie do zlokalizowania tego, co powinno być nieustawione. W końcu, gdyby istniały, nadal można by się spodziewać, że oboje będą później. NIE chciałbyś, aby cała tablica zniknęła tylko dlatego, że usunąłeś () jeden z jej elementów!

Pan Smith
źródło
41
To wymaga trochę więcej wyjaśnień. Możesz usunąć klucze tablicy, które nie są zdefiniowane, o ile sama tablica istnieje.
kingmaple
@kristovaher Rzeczywiście - to w ogóle nie dotyczy konkretnego scenariusza, który opisuje PO.
Mark Amery,
21

Użycie unsetna niezdefiniowanej zmiennej nie spowoduje żadnych błędów (chyba że zmienna jest indeksem tablicy (lub obiektu), który nie istnieje).

Dlatego jedyne, co musisz wziąć pod uwagę, to to, co jest najbardziej wydajne. Bardziej efektywne jest nie testowanie z „isset”, jak pokaże mój test.

Test:

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();

Wyniki:

  1. Function A time = 1.0307259559631
    • Zdefiniowany bez isset
  2. Function B time = 0.72514510154724
    • Niezdefiniowane bez isset
  3. Function C time = 1.3804969787598
    • Zdefiniowane za pomocą isset
  4. Function D time = 0.86475610733032
    • Niezdefiniowane za pomocą isset

Wniosek:

Jest zawsze mniej efektywny w użyciu isset, nie wspominając o niewielkiej ilości dodatkowego czasu potrzebnego na napisanie. Szybciej jest spróbować unsetużyć niezdefiniowanej zmiennej niż sprawdzić, czy to możliwe unset.

Dan Bray
źródło
1
To o wiele lepsze niż zaakceptowana odpowiedź! Dzięki za przeprowadzenie tych testów.
Adam Friedman
3

Jeśli chcesz usunąć ustawienie zmiennej, możesz po prostu użyć unset

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

Sprawdzanie jej istnienia nie przynosi żadnych korzyści przy próbie cofnięcia ustawienia zmiennej.

Jeśli zmienna jest tablicą i chcesz usunąć ustawienie elementu, musisz upewnić się, że rodzic istnieje jako pierwszy, dotyczy to również właściwości obiektu.

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

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

To jest rozwiązywane przez owijanie unsetw if(isset($var)){ ... }bloku.

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

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

Powodem, dla którego sprawdzamy tylko zmienną ( rodzica ), jest po prostu to, że nie musimy sprawdzać właściwości / elementu, a pisanie i obliczanie byłoby dużo wolniejsze, ponieważ wymagałoby to dodatkowego sprawdzenia.

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)){
...
}

Jest to oczywiste, ale ważne jest również, aby znać typezmienną podczas pobierania, ustawiania i rozbrajania elementu lub właściwości; użycie złej składni spowoduje zgłoszenie błędu.

To samo dzieje się przy próbie cofnięcia wartości wielowymiarowej tablicy lub obiektu. Musisz upewnić się, że klucz / nazwa nadrzędna istnieje.

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

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

Kiedy mamy do czynienia z przedmiotami, należy pomyśleć o innej rzeczy, a jest to widoczność.

To, że istnieje, nie oznacza, że ​​masz uprawnienia do jego modyfikacji.

TarranJones
źródło
Wreszcie właściwa odpowiedź. Dziękuję Ci.
wp78de
Mała aktualizacja: W PHP 7.4 / 8.0 żaden błąd nie jest generowany, gdy masz unsetwłaściwość nieistniejącego obiektu nadrzędnego. Jednak rozłożenie klucza w nieistniejącej tablicy w PHP8 powoduje nie tylko powiadomienie, ale także ostrzeżenie (może ulec zmianie).
wp78de
1

Sprawdź ten link https://3v4l.org/hPAto

Narzędzie online pokazuje zgodność kodu z różnymi wersjami PHP

Zgodnie z tym narzędziem kod

unset($_SESSION['signup_errors']);

działałoby dla PHP> = 5.4.0 bez podawania żadnych powiadomień / ostrzeżeń / błędów.

evgpisarchik
źródło