isset() will return FALSE if testing a variable that has been set to NULL.
Zasadniczo isset()
nie sprawdza, czy zmienna jest w ogóle ustawiona, ale czy jest ustawiona na cokolwiek innego NULL
.
Biorąc to pod uwagę, jaki jest najlepszy sposób sprawdzenia istnienia zmiennej? Próbowałem czegoś takiego:
if(isset($v) || @is_null($v))
( @
jest to konieczne, aby uniknąć ostrzeżenia, gdy $v
nie jest ustawione), ale is_null()
ma podobny problem jak isset()
: zwraca TRUE
zmienne nieustawione! Wydaje się również, że:
@($v === NULL)
działa dokładnie tak @is_null($v)
, więc to też nie działa .
Jak mamy rzetelnie sprawdzać istnienie zmiennej w PHP?
Edycja: w PHP istnieje wyraźna różnica między zmiennymi, które nie są ustawione, a zmiennymi, które są ustawione na NULL
:
<?php
$a = array('b' => NULL);
var_dump($a);
PHP pokazuje, że $a['b']
istnieje i ma NULL
wartość. Jeśli dodasz:
var_dump(isset($a['b']));
var_dump(isset($a['c']));
widać niejednoznaczność, o której mówię z isset()
funkcją. Oto wynik wszystkich trzech z nich var_dump()s
:
array(1) {
["b"]=>
NULL
}
bool(false)
bool(false)
Dalsza edycja: dwie rzeczy.
Po pierwsze, przypadek użycia. Tablica jest przekształcana w dane UPDATE
instrukcji SQL , gdzie klucze tablicy są kolumnami tabeli, a wartości tablicy są wartościami, które należy zastosować do każdej kolumny. Każda kolumna tabeli może zawierać NULL
wartość, oznaczoną przez przekazanie NULL
wartości do tablicy. Państwo potrzebuje sposobu na odróżnienie klucza tablicy nie istniejącą, a wartość tablicy jest ustawiany na NULL
; to jest różnica między nie aktualizowaniem wartości kolumny a aktualizowaniem wartości kolumny do NULL
.
Po drugie, odpowiedź Zoredache za , array_key_exists()
działa poprawnie na moim powyższym przypadku użycia i wszelkich zmiennych globalnych:
<?php
$a = NULL;
var_dump(array_key_exists('a', $GLOBALS));
var_dump(array_key_exists('b', $GLOBALS));
wyjścia:
bool(true)
bool(false)
Ponieważ to właściwie obsługuje prawie wszędzie, widzę, że istnieje jakakolwiek dwuznaczność między zmiennymi, które nie istnieją, a zmiennymi ustawionymi NULL
, dlatego nazywam array_key_exists()
oficjalny najprostszy sposób w PHP, aby naprawdę sprawdzić istnienie zmiennej .
(Jedyny inny przypadek, jaki mogę wymyślić, dotyczy właściwości klasy, dla których istnieje property_exists()
, zgodnie z jego dokumentacją , działa podobnie do array_key_exists()
tego, że właściwie rozróżnia brak ustawienia i ustawienie NULL
).
register_globals
, wciąż mam problem z sytuacją, w której nawet to wymagałoby takiego rozróżnienia, ponieważ wszystko zarejestrowane z żądania HTTP zawsze byłoby ciągiem, a nie ciągiemnull
.Odpowiedzi:
Jeśli sprawdzana zmienna byłaby w zasięgu globalnym, możesz:
źródło
$defined_vars = get_defined_vars();
a następnie przetestować za pomocąarray_key_exists('v', $defined_vars);
.isset($foo[$bar])
staje sięarray_key_exists($bar, $foo)
property_exists
wydaje się obiecujące, z wyjątkiem tego:> Funkcja property_exists () nie może wykryć właściwości, które są magicznie dostępne przy użyciu metody magicznej __get.Próba przedstawienia przeglądu różnych dyskusji i odpowiedzi:
Nie ma jednej odpowiedzi na pytanie, która zastąpiłaby wszystkie
isset
możliwe sposoby . Niektóre przypadki użycia są rozwiązywane przez inne funkcje, podczas gdy inne nie poddają się kontroli lub mają wątpliwą wartość poza kodowaniem. Inne przypadki użycia nie są „zepsute” ani „niespójne”, ale pokazują, dlaczegoisset
reakcja na nienull
jest logicznym zachowaniem.Rzeczywiste przypadki użycia (z rozwiązaniami)
1. Klucze tablic
Tablice mogą być traktowane jak zbiory zmiennych, ze
unset
iisset
traktując je tak, jakby były. Ponieważ jednak można je powtarzać, zliczać itp., Brakująca wartość nie jest taka sama jak wartość, której wartość jestnull
.Odpowiedzią w tym przypadku jest użycie
array_key_exists()
zamiastisset()
.Ponieważ wymaga to sprawdzenia tablicy jako argumentu funkcji, PHP nadal będzie generować „powiadomienia”, jeśli sama tablica nie istnieje. W niektórych przypadkach można zasadnie argumentować, że każdy wymiar powinien zostać zainicjowany jako pierwszy, więc zawiadomienie wykonuje swoją pracę. W innych przypadkach
array_key_exists
funkcja „rekurencyjna” , która z kolei sprawdza każdy wymiar tablicy, unikałaby tego, ale zasadniczo byłaby taka sama jak@array_key_exists
. Jest to również nieco styczne do obsługinull
wartości.2. Właściwości obiektu
W tradycyjnej teorii programowania obiektowego enkapsulacja i polimorfizm są kluczowymi właściwościami obiektów; w implementacji klasy oparte OOP jak PHP, kapsułkowane właściwości są zadeklarowane jako część definicji klasy, a biorąc pod uwagę poziomy dostępu (
public
,protected
, lubprivate
).Jednak PHP pozwala również dynamicznie dodawać właściwości do obiektu, tak jak klucze do tablicy, a niektórzy ludzie używają obiektów bezklasowych (technicznie instancji wbudowanej
stdClass
, która nie ma metod ani funkcji prywatnej) w podobny sposób droga do tablic asocjacyjnych. Prowadzi to do sytuacji, w których funkcja może chcieć wiedzieć, czy dana właściwość została dodana do danego obiektu.Podobnie jak w przypadku kluczy tablic, w języku znajduje się rozwiązanie do sprawdzania właściwości obiektu, zwane, w miarę rozsądnym,
property_exists
.Przypadki użycia, których nie można uzasadnić, z dyskusją
3.
register_globals
i inne zanieczyszczenia globalnej przestrzeni nazwregister_globals
Funkcja dodana do zakresu zmiennych globalnych, których nazwiska zostały określone przez aspektów żądania HTTP (GET i POST parametrów i ciasteczka). Może to prowadzić do błędnego i niepewnego kodu, dlatego został domyślnie wyłączony od wersji PHP 4.2 wydanej w sierpniu 2000 r. I całkowicie usunięty w wersji PHP 5.4 wydanej w marcu 2012 r . Możliwe jest jednak, że niektóre systemy nadal działają z włączoną lub emulowaną tą funkcją. Możliwe jest również „zanieczyszczenie” globalnej przestrzeni nazw na inne sposoby, za pomocąglobal
słowa kluczowego lub$GLOBALS
tablicy.Po pierwsze,
register_globals
jest mało prawdopodobne , że sama nieoczekiwanie wytworzynull
zmienną, ponieważ wartości GET, POST i cookie zawsze będą ciągami znaków (z''
ciągle wracającymitrue
zisset
), a zmienne w sesji powinny być całkowicie pod kontrolą programisty.Po drugie, zanieczyszczenie zmiennej o wartości
null
stanowi problem tylko wtedy, gdy spowoduje to nadpisanie niektórych wcześniejszych inicjalizacji. „Nadpisywanie” niezainicjowanej zmiennejnull
byłoby problematyczne, gdyby kod gdzieś indziej rozróżniał oba te stany, więc sama ta możliwość stanowi argument przeciwko takiemu rozróżnieniu.4.
get_defined_vars
icompact
Kilka rzadko używanych funkcji w PHP, takich jak
get_defined_vars
icompact
, pozwala traktować nazwy zmiennych tak, jakby były kluczami w tablicy. W przypadku zmiennych globalnych tablica superglobalna$GLOBALS
umożliwia podobny dostęp i jest bardziej powszechna. Te metody dostępu będą zachowywać się inaczej, jeśli zmienna nie zostanie zdefiniowana w odpowiednim zakresie.Gdy zdecydujesz się traktować zestaw zmiennych jako tablicę za pomocą jednego z tych mechanizmów, możesz wykonać na nim wszystkie te same operacje, co na dowolnej normalnej tablicy. W związku z tym patrz 1.
Funkcjonalność, która istniała tylko po to, by przewidzieć, jak te funkcje będą się zachowywać (np. „Czy w tablicy zwróci się klucz„ foo ”
get_defined_vars
?)) Jest zbędna, ponieważ można po prostu uruchomić tę funkcję i dowiedzieć się bez żadnych niepożądanych efektów.4a Zmienne zmienne (
$$foo
)Chociaż nie do końca takie same, jak funkcje, które zamieniają zestaw zmiennych w tablicę asocjacyjną, większość przypadków wykorzystujących „zmienne zmienne” („przypisanie do zmiennej nazwanej na podstawie tej innej zmiennej”) może i powinna zostać zmieniona, aby zamiast tego użyć tablicy asocjacyjnej .
Zasadniczo nazwa zmiennej jest etykietą nadaną wartości przez programistę; jeśli określasz to w czasie wykonywania, tak naprawdę nie jest to etykieta, ale klucz w sklepie z kluczowymi wartościami. Praktycznie, nieużywając tablicy, tracisz zdolność liczenia, iterowania itp .; może również okazać się niemożliwe posiadanie zmiennej „poza” składnicą klucz-wartość, ponieważ może zostać ona nadpisana
$$foo
.Po zmianie na użycie tablicy asocjacyjnej kod będzie podlegał rozwiązaniu 1. Pośredni dostęp do właściwości obiektu (np.
$foo->$property_name
) Można rozwiązać za pomocą rozwiązania 2.5.
isset
jest o wiele łatwiejszy do pisania niżarray_key_exists
Nie jestem pewien, czy to jest naprawdę istotne, ale tak, nazwy funkcji PHP mogą być czasem dość skomplikowane i niespójne. Najwyraźniej w prehistorycznych wersjach PHP użyto długości nazwy funkcji jako klucza skrótu, więc Rasmus celowo wymyślił nazwy funkcji
htmlspecialchars
tak, aby miały niezwykłą liczbę znaków ...Ale przynajmniej nie piszemy w Javie, co? ;)
6. Niezainicjowane zmienne mają typ
Strona podręcznika na temat zmiennych podstawowych zawiera następujące stwierdzenie:
Nie jestem pewien, czy w Zend Engine istnieje jakieś pojęcie „niezainicjowanego, ale znanego typu”, czy też czyta to zbyt wiele w oświadczeniu.
Oczywiste jest, że nie ma to praktycznego wpływu na ich zachowanie, ponieważ zachowania opisane na tej stronie dla niezainicjowanych zmiennych są identyczne z zachowaniem zmiennej, której wartość jest
null
. Aby wybrać jeden z przykładów, jak$a
i$b
w tym kodzie skończy się jako liczbę całkowitą42
:(Pierwszy podniesie powiadomienie o niezadeklarowanej zmiennej, próbując sprawić, że napiszesz lepszy kod, ale nie będzie miało to żadnego wpływu na to, jak naprawdę działa kod.)
99. Wykrywanie, czy funkcja się uruchomiła
(Zachowaj ten ostatni, ponieważ jest znacznie dłuższy niż inne. Może później go zmodyfikuję ...)
Rozważ następujący kod:
Jeśli
some_function
może wrócićnull
, istnieje możliwość, żeecho
nie zostanie osiągnięty, nawet jeśli zostaniesome_test
zwróconytrue
. Intencją programisty było wykrycie, kiedy$result
nigdy nie zostało ustawione, ale PHP nie pozwala na to.Istnieją jednak inne problemy z tym podejściem, które stają się jasne, jeśli dodasz zewnętrzną pętlę:
Ponieważ
$result
nigdy nie jest jawnie inicjowany, nabierze wartości po przejściu pierwszego testu, uniemożliwiając stwierdzenie, czy kolejne testy przeszły, czy nie. To jest naprawdę bardzo częsty błąd, gdy zmienne nie są poprawnie inicjowane.Aby to naprawić, musimy zrobić coś na linii, w której skomentowałem, że czegoś brakuje. Najbardziej oczywistym rozwiązaniem jest ustawienie
$result
„wartości końcowej”, którasome_function
nigdy nie może powrócić; jeśli taknull
, reszta kodu będzie działać poprawnie. Jeśli nie ma naturalnego kandydata na wartość końcową, ponieważsome_function
ma wyjątkowo nieprzewidywalny typ zwracany (który prawdopodobnie sam w sobie jest złym znakiem),$found
można zamiast tego użyć np. Dodatkowej wartości logicznej .Pierwszy eksperyment myślowy:
very_null
stałaPHP teoretycznie może zapewnić specjalną stałą - a także
null
- do wykorzystania jako wartość końcową tutaj; prawdopodobnie zwrócenie tego z funkcji byłoby nielegalne lub byłoby do tego przymuszonenull
, i to samo prawdopodobnie dotyczyłoby przekazania go jako argumentu funkcji. To sprawiłoby, że ten bardzo konkretny przypadek byłby nieco prostszy, ale jak tylko zdecydowałbyś ponownie rozłożyć kod - na przykład, aby umieścić wewnętrzną pętlę w osobnej funkcji - stałby się bezużyteczny. Jeśli stała mogłaby być przekazywana między funkcjami, nie można zagwarantować,some_function
że jej nie zwróci, więc nie byłaby użyteczna jako uniwersalna wartość końcowa.Argument wykrywania niezainicjowanych zmiennych w tym przypadku sprowadza się do argumentu dla tej specjalnej stałej: jeśli zastąpisz komentarz
unset($result)
i potraktujesz to inaczej$result = null
, wprowadzisz „wartość”$result
, której nie można przekazać, a jedynie wykryte przez określone funkcje wbudowane.Myśl eksperyment drugi: licznik przydziału
Innym sposobem myślenia o to, o co
if
pyta ostatni, jest „czy coś ma jakieś zadanie$result
?” Zamiast uważać to za specjalną wartość$result
, można by pomyśleć o tym jako o „metadanych” o zmiennej, trochę jak o „zabarwieniu zmiennych” przez Perla. Więc raczej niżisset
można to nazwaćhas_been_assigned_to
, i zamiastunset
,reset_assignment_state
.Ale jeśli tak, to po co zatrzymywać się na boolean? Co jeśli chcesz wiedzieć, ile razy test przeszedł pomyślnie; możesz po prostu rozszerzyć swoje metadane na liczbę całkowitą i mieć
get_assignment_count
ireset_assignment_count
...Oczywiście dodanie takiej funkcji miałoby kompromis w zakresie złożoności i wydajności języka, dlatego należałoby dokładnie rozważyć jego oczekiwaną przydatność. Podobnie jak w przypadku
very_null
stałej, byłby użyteczny tylko w bardzo wąskich okolicznościach i byłby podobnie odporny na ponowne faktoring.Mam nadzieję, że oczywiste pytanie brzmi, dlaczego silnik wykonawczy PHP powinien z góry założyć, że chcesz śledzić takie rzeczy, zamiast pozostawić to jawne, używając normalnego kodu.
źródło
Czasami trochę się gubię, próbując dowiedzieć się, której operacji porównania użyć w danej sytuacji.
isset()
dotyczy tylko niezainicjowanych lub jawnie zerowych wartości. Przekazywanie / przypisywanie wartości null to świetny sposób na zapewnienie logicznego porównania zgodnego z oczekiwaniami.Mimo to trudno jest o tym myśleć, dlatego oto prosta macierz porównująca, w jaki sposób różne wartości będą oceniane przez różne operacje:
Aby dopasować się do stołu, nieco skompresowałem etykiety:
$a;
odnosi się do zadeklarowanej, ale nieprzypisanej zmiennej$a = null;
$a = [];
$a = 0;
$a === null
isset($a)
empty($a)
$a ? true : false
Wszystkie wyniki są logiczne,
true
są drukowane ifalse
pomijane.Możesz uruchomić testy samodzielnie, sprawdź tę treść:
https://gist.github.com/mfdj/8165967
źródło
"0"
do tabeli, aby uzyskać kompletność i przejrzystośćempty
operacjiMożesz użyć konstrukcji języka kompaktowego do testowania istnienia zmiennej zerowej. Zmienne, które nie istnieją, nie pojawią się w wyniku, a pojawią się wartości null.
W przypadku twojego przykładu:
Oczywiście dla zmiennych w zakresie globalnym można również użyć array_key_exists ().
Btw osobiście unikałbym sytuacji takich jak zaraza, w której istnieje znacząca różnica między zmienną nieistniejącą a zmienną o wartości zerowej. PHP i większość innych języków po prostu tak nie uważa.
źródło
NULL
. SemantycznieNULL
powinno oznaczać „brak zasobu”, ale brak zdefiniowania zmiennej jest błędem programisty.undefined
inull
są tak rzadkie, że nie mogę tego przegapić. IMHO, głównym zastosowaniemundefined
jest „błąd programisty w języku innym niż ścisły”. W ścisłym języku, jeśli potrzebuję odrębnego stanuclient did not state a value
, to deklaruję wartość odpowiednią do sytuacji i testuję ją. W najgorszym przypadku trzeba dodać osobną zmienną flagi. Ale robienie tego rzadko jest lepsze niż ZAWSZE radzenie sobie z DWÓMI różnymi stanami nie-wartościowymi !!Wyjaśniając NULL, logicznie myśląc
Myślę, że oczywistą odpowiedzią na to wszystko jest ... Nie inicjuj swoich zmiennych jako NULL, inicjuj je jako coś istotnego dla tego, czym mają się stać.
Traktuj NULL prawidłowo
NULL należy traktować jako „nieistniejącą wartość”, co oznacza NULL. Zmiennej nie można zaklasyfikować jako istniejącej w PHP, ponieważ nie powiedziano jej, jaki typ encji próbuje być. Może i nie istnieje, więc PHP po prostu mówi: „Dobrze, nie ma, bo i tak nie ma sensu, a NULL to mój sposób na powiedzenie tego”.
Kłótnia
Spierajmy się teraz. „Ale NULL jest jak powiedzenie 0, FAŁSZ lub„ ”.
Źle, 0-FAŁSZ- '' są nadal klasyfikowane jako puste wartości, ale SĄ one określone jako pewnego rodzaju wartość lub z góry określona odpowiedź na pytanie. FAŁSZ jest odpowiedzią na tak lub nie, '' jest odpowiedzią na tytuł, który ktoś przesłał, a 0 jest odpowiedzią na ilość lub czas itp. Są one ustawione jako pewnego rodzaju odpowiedź / wynik, co sprawia, że są ważne jako ustawione.
NULL to po prostu żadna odpowiedź, która tak zawsze, nie mówi nam tak lub nie i nie podaje nam czasu i nie mówi nam, że przesłano pusty ciąg znaków. To podstawowa logika w rozumieniu wartości NULL.
Podsumowanie
Nie chodzi o tworzenie zwariowanych funkcji w celu obejścia problemu, ale po prostu zmienia sposób, w jaki mózg patrzy na NULL. Jeśli ma wartość NULL, załóż, że nie jest ustawiony jako cokolwiek. Jeśli wstępnie definiujesz zmienne, zdefiniuj je jako 0, FAŁSZ lub „” w zależności od zamierzonego zastosowania.
Możesz to zacytować. To jest poza moją logiczną głową :)
źródło
isset($a['x'])
powie ci fałsz, jeślix
jest null, ale pojawi się wcount($a)
..compact
będzie działać na wszystkich ustawionych zmiennych, w tymnulls
i tak dalej.Właściwości obiektu można sprawdzić pod kątem istnienia za pomocą property_exists
Przykład z testu jednostkowego:
źródło
Jako dodatek do dyskusji greatbigmassive o tym, co oznacza NULL , zastanów się, co tak naprawdę oznacza „istnienie zmiennej”.
W wielu językach musisz jawnie zadeklarować każdą zmienną przed użyciem ; może to determinować jego typ, ale co ważniejsze deklaruje jego zakres . Zmienna „istnieje” wszędzie w swoim zakresie i nigdzie poza nią - może to być cała funkcja lub pojedynczy „blok”.
W swoim zakresie zmienna przypisuje pewne znaczenie etykiecie, którą wybrałeś jako programista. Poza zakresem etykieta ta nie ma znaczenia (to, czy używasz tej samej etykiety w innym zakresie, jest w zasadzie nieistotne).
W PHP zmienne nie muszą być deklarowane - pojawiają się, gdy tylko są potrzebne. Kiedy piszesz do zmiennej po raz pierwszy, PHP przydziela wpis w pamięci dla tej zmiennej. Jeśli czytasz ze zmiennej, która obecnie nie ma pozycji, PHP uważa tę zmienną za posiadającą wartość
NULL
.Jednak automatyczne detektory jakości kodu generalnie ostrzegają, jeśli użyjesz zmiennej bez jej „inicjalizacji”. Po pierwsze, pomaga to wykryć literówki, takie jak przypisywanie do,
$thingId
ale czytanie z$thing_id
; ale po drugie, zmusza cię do rozważenia zakresu, w którym ta zmienna ma znaczenie, tak jak deklaracja.Każdy kod, który dba o to, czy zmienna „istnieje”, jest częścią zakresu tej zmiennej - niezależnie od tego, czy została ona zainicjowana, jako programista nadałeś tej etykiecie znaczenie w tym punkcie kodu. Ponieważ go używasz, musi w pewnym sensie „istnieć”, a jeśli istnieje, musi mieć wartość domyślną; w PHP ta domyślna wartość to
null
.Ze względu na sposób działania PHP możliwe jest pisanie kodu, który traktuje przestrzeń nazw istniejących zmiennych nie jako zakres etykiet, którym nadałeś znaczenie, ale jako pewnego rodzaju magazyn klucz-wartość. Można na przykład uruchomić kod jak poniżej:
$var = $_GET['var_name']; $$var = $_GET['var_value'];
. To, że potrafisz, nie oznacza, że to dobry pomysł.Okazuje się, że PHP ma znacznie lepszy sposób reprezentowania magazynów klucz-wartość, zwanych tablicami asocjacyjnymi. I chociaż wartości tablicy można traktować jak zmienne, można również wykonywać operacje na tablicy jako całości. Jeśli masz tablicę asocjacyjną, możesz sprawdzić, czy zawiera ona klucz, używając
array_key_exists()
.Możesz także używać obiektów w podobny sposób, dynamicznie ustawiając właściwości, w takim przypadku możesz używać
property_exists()
dokładnie w ten sam sposób. Oczywiście, jeśli zdefiniowanie klasy, można zadeklarować właściwości, które to - można nawet wybrać pomiędzypublic
,private
iprotected
zakres.Chociaż istnieje różnica techniczna między zmienną (w przeciwieństwie do klucza tablicy lub właściwości obiektu), która nie została zainicjowana (lub która została jawnie
unset()
), a tą, której wartością jestnull
dowolny kod, który uważa tę różnicę za znaczącą używa zmiennych w sposób, w jaki nie powinny być używane.źródło
isset()
zachowuje?”.null
. To, czy ta wartość istnieje, zanim się na nią spojrzy, jest kwestią dla filozofów, ale jeśli chodzi o wszelkie obserwowalne zachowania, wartość jest konsekwentnanull
.isset
sprawdza, czy zmienna jest ustawiona, a jeśli tak, to czy jej wartość nie jest równa NULL. Ta ostatnia część (moim zdaniem) nie wchodzi w zakres tej funkcji. Nie ma przyzwoitego obejścia, aby ustalić, czy zmienna ma wartość NULL ponieważ nie jest ustawiona lub ponieważ jest jawnie ustawiona na NULL .Oto jedno z możliwych rozwiązań:
Innym obejściem jest sondowanie danych wyjściowych
get_defined_vars()
:źródło
Nie zgadzam się z twoim rozumowaniem na temat wartości NULL , a mówienie, że musisz zmienić sposób myślenia o wartości NULL, jest po prostu dziwne.
Myślę, że isset () nie został poprawnie zaprojektowany, isset () powinien powiedzieć ci, czy zmienna została ustawiona i nie powinna zajmować się faktyczną wartością zmiennej.
Co jeśli sprawdzasz wartości zwrócone z bazy danych, a jedna z kolumn ma wartość NULL, nadal chcesz wiedzieć, czy istnieje, nawet jeśli wartość wynosi NULL ... tutaj nie ufaj isset () tutaj.
również
isset () powinien być zaprojektowany tak, aby działał w następujący sposób:
w ten sposób pozostawiamy programistom sprawdzenie typów, a nie pozostawienie go do isset (), aby założyć, że nie ma go tam, ponieważ wartość wynosi NULL - to po prostu głupi projekt
źródło
array_key_exists
. Nigdy nie powinieneś znajdować się w sytuacji, w której w czasie wykonywania nie wiesz, czy istnieje rzeczywista zmienna.register_globals
, twoja odpowiedź nie jest zmianą naisset()
. Podręcznik PHP wspomina „naprawdę dobrą praktyką programistyczną jest najpierw inicjowanie zmiennych”, które rozwiązuje sięregister_globals
w czasie projektowania, a nie w czasie wykonywania. Dostępna jest również pozycja FAQ, która zawieraunregister_globals()
funkcję radzenia sobie z nią w czasie wykonywania.Dodam do tego szybkie dwa centy. Jednym z powodów, dla których ten problem jest mylący, jest to, że ten scenariusz wydaje ten sam wynik, gdy raportowanie błędów nie jest pełne:
Na podstawie tego wyniku można założyć, że różnica między
$a = null
definicją a jej brakiem$b
jest niczym.Zgłaszanie błędu korby:
Uwaga: zgłosił błąd niezdefiniowanej zmiennej, ale wartość wyjściowa
var_dump
nadal jestNULL
.PHP oczywiście ma wewnętrzną zdolność do rozróżniania zmiennej pustej od zmiennej niezdefiniowanej. Wydaje mi się, że powinna istnieć wbudowana funkcja sprawdzania tego.
Myślę, że zaakceptowana odpowiedź jest w większości dobra, ale gdybym miał ją wdrożyć, napisałbym dla niej opakowanie. Jak wcześniej wspomniano w tej odpowiedzi , muszę zgodzić się, że tak naprawdę nie spotkałem się z sytuacją, w której był to problem. Wydaje mi się, że prawie zawsze kończy się na scenariuszu, w którym moje zmienne są albo ustawione i zdefiniowane, albo nie są (niezdefiniowane, nieustawione, zerowe, puste itd.). Nie mówiąc już o tym, że taka sytuacja nie wystąpi w przyszłości, ale ponieważ wydaje się to być dość wyjątkowym problemem, nie dziwię się, że deweloperzy PHP nie zadali sobie trudu, aby to zrobić.
źródło
Jeśli uruchomię następujące:
Dostaję błąd:
Jeśli uruchomię następujące:
Nie dostaję błędu.
Jeśli mam zmienną, którą należy ustawić, zwykle robię coś takiego.
lub
W ten sposób, w dalszej części skryptu, mogę bezpiecznie używać $ foo i wiem, że „jest ustawiony” i że domyślnie ma wartość null. Później mogę,
if ( is_null($foo) ) { /* ... */ }
jeśli muszę i wiem na pewno, że zmienna istnieje, nawet jeśli jest pusta.Pełna dokumentacja isset zawiera więcej niż tylko to, co początkowo zostało wklejone. Tak, zwraca false dla zmiennej, która była wcześniej ustawiona, ale teraz ma wartość NULL, ale zwraca również false, jeśli zmienna nie została jeszcze ustawiona (kiedykolwiek) i dla każdej zmiennej, która została oznaczona jako nieustawiona. Zauważa również, że bajt NULL („\ 0”) nie jest uważany za pusty i zwróci wartość true.
źródło
Spróbuj użyć
Wydaje się, że zmienna nie jest ustawiona tylko wtedy, gdy jest specyficznie rozbrojona ($ v). Wygląda na to, że twoje znaczenie „istnienia” różni się od definicji PHP. NULL z pewnością istnieje, jest NULL.
źródło
Muszę powiedzieć przez wszystkie lata programowania PHP, że nigdy nie spotkałem się z problemem
isset()
zwracania wartości false w zmiennej null. OTOH, napotkałem problemy zisset()
niepowodzeniem przy wpisie pustej tablicy - alearray_key_exists()
w takim przypadku działa poprawnie.Dla porównania, Icon wyraźnie definiuje nieużywaną zmienną jako zwracaną,
&null
więc używasz testu is-null w Icon, aby również sprawdzić, czy nie jest ustawiona zmienna. To ułatwia rzeczy. Z drugiej strony Visual BASIC ma wiele stanów dla zmiennej, która nie ma wartości (Null, Empty, Nothing, ...), i często trzeba sprawdzać więcej niż jeden z nich. Jest to znane jako źródło błędów.źródło
Zgodnie z instrukcją PHP dla funkcji empty (): „Ustal, czy zmienna jest uważana za pustą. Zmienna jest uważana za pustą, JEŚLI NIE ISTNIEJE lub jeśli jej wartość jest równa FAŁSZ. Pusta () nie generuje ostrzeżenia, jeśli właściwość zmienna nie istnieje. ” (Podkreślam.) Oznacza to, że funkcja empty () powinna kwalifikować się jako „najlepszy sposób na sprawdzenie istnienia zmiennej w PHP”, zgodnie z tytułem Pytanie.
Nie jest to jednak wystarczające, ponieważ funkcję empty () można oszukać za pomocą zmiennej, która istnieje i jest ustawiona na NULL.
Przerywam moją wcześniejszą odpowiedź, aby przedstawić coś lepszego, ponieważ jest to mniej kłopotliwe niż moja pierwotna odpowiedź (która następuje po tej przerwie, dla porównania).
Dwie proste linie kodu mogą wykorzystać powyższą funkcję do ujawnienia, czy zmienna jest niezdefiniowana:
Możesz podążać za tymi dwoma wierszami we właściwy sposób, na przykład w tym przykładzie:
Chciałem umieścić wywołanie funkcji ob_start () i ($ testvar === null) wewnątrz funkcji i po prostu przekazać zmienną do funkcji, ale to nie działa. Nawet jeśli spróbujesz użyć funkcji „przekaż referencję” zmiennej do funkcji, zmienna BECOMES została zdefiniowana, a wtedy funkcja nigdy nie wykryje, że poprzednio była niezdefiniowana. Przedstawiono tu kompromis między tym, co chciałem zrobić, a tym, co faktycznie działa.
Z powyższego wynika, że istnieje inny sposób na zawsze uniknięcie komunikatu o błędzie „Niezdefiniowana zmienna”. (Założenie jest takie, że zapobieganie takiemu komunikatowi jest powodem, dla którego chcesz przetestować, czy zmienna jest niezdefiniowana).
Po prostu wywołaj tę funkcję, zanim zrobisz coś z $ testvar:
Oczywiście wartość nowo utworzonej instancji jest ustawiona na null!
(Przerwanie kończy się)
Po kilku studiach i eksperymentach, oto coś, co zadziała:
Wyjaśnienie: Zmienna $ er jest inicjowana na wartość domyślną „brak błędu”. Zdefiniowano „funkcję modułu obsługi”. Jeśli $ testvar (zmienna, którą chcemy wiedzieć, czy jest niezdefiniowana) przejdzie wstępny test funkcji pustej (), wówczas przeprowadzimy dokładniejszy test. Wywołujemy funkcję set_error_handler (), aby użyć wcześniej zdefiniowanej funkcji modułu obsługi. Następnie wykonujemy proste porównanie tożsamości z udziałem $ testvar, KTÓRE JEŚLI NIEODDEFINOWANE SPOWODUJE BŁĄD. Funkcja modułu obsługi przechwytuje błąd i konkretnie sprawdza, czy przyczyną błędu jest fakt, że zmienna jest niezdefiniowana. Wynik jest umieszczany w zmiennej $ er informacji o błędach, którą możemy później przetestować, aby zrobić wszystko, co chcemy, w wyniku pewności, czy $ testvar został zdefiniowany. Ponieważ potrzebujemy tylko funkcji obsługi do tego ograniczonego celu, przywracamy pierwotną funkcję obsługi błędów. Funkcję „myHndlr” należy zadeklarować tylko raz; drugi kod można skopiować do odpowiednich miejsc, dla $ testvar lub dowolnej innej zmiennej, którą chcemy przetestować w ten sposób.
źródło
inst
funkcja jest w zasadzie podobna do@
operatora tłumienia błędów: „Wiem, że robię tu coś złego, ale chcę tylko, aby ten komunikat zniknął, nie zmieniając w żaden sposób działania mojego kodu”.Myślę, że jedynym rozwiązaniem jest pełna do zgłaszania zawiadomień o
Ale będziesz musiał naprawić wszystkie powiadomienia generowane między innymi przez niezdefiniowane zmienne, stałe, klucze tablicy, właściwości klasy. Gdy to zrobisz, nie będziesz musiał martwić się różnicą między zmiennymi zerowymi i niezadeklarowanymi, a dwuznaczność znika.
Włączenie raportowania powiadomień może nie być dobrą alternatywą we wszystkich sytuacjach, ale istnieją dobre powody, aby je włączyć:
Dlaczego powinienem naprawić błędy E_NOTICE?
W moim przypadku ponad rok pracował w proyectie bez niego, ale był używany, aby zachować ostrożność przy deklarowaniu zmiennych, więc przejście było szybkie.
źródło
Jedynym sposobem na sprawdzenie, czy zmienna jest zdefiniowana w bieżącym zakresie (
$GLOBALS
nie jest wiarygodna), jestarray_key_exists( 'var_name', get_defined_vars() )
.źródło
Wolę używać opcji „pusty” jako najlepszej metody sprawdzania istnienia zmiennej, że a) istnieje, a b) nie jest pusta.
źródło
empty()
nie sprawdza, czy zmienna ma wartość null, sprawdza czy to fałszywy-y, na przykład nie jedną z""
(pusty ciąg znaków),0
(0 jako liczbę całkowitą)0.0
(0 jako float),"0"
(0 jako ciąg znaków)NULL
,FALSE
,array()
(pusta tablica) i$var;
(zmienna zadeklarowana, ale bez wartości). Załóżmy, że masz wymagane pole radiowe w formie z dwoma wejściami z wartościami0
i1
. Jeśli użyjeszempty()
do sprawdzania poprawności, a użytkownik wybierze to0
, nieumyślnie popełnisz błąd „wymagane pole nie może być puste”. Zobacz instrukcję php.net/manual/en/function.empty.php