Nie można użyć wartości zwracanej przez metodę w kontekście zapisu


465

Sądzę, że następujący fragment kodu powinien działać, ale nie działa (edytowano: Teraz działa w PHP 5.5+) :

if (!empty($r->getError()))

Gdzie getError()jest po prostu:

public function getError()
{
    return $this->error;
}

Jednak kończę na tym błędzie:

nie można użyć wartości zwracanej przez metodę w kontekście zapisu

Co to znaczy? Czy to nie tylko czytanie?


2
Prawdopodobnie w PHP 5.5 będziesz mógł przekazywać wyrażenia na empty: wiki.php.net/rfc/empty_isset_exprs
Carlos Campderrós


Ok, uważam, że odpowiedź porneL jest poprawna również w moim kodzie, if ( !$e->find('div') ) który sprawdza, czy bieżący element DOM HTML jest pusty, czy nie. Używam go w wewnętrznej pętli, aby wydrukować tylko jedną div bez wewnętrznej div.
Salem,

Odpowiedzi:


769

empty() musi uzyskać dostęp do wartości przez referencję (w celu sprawdzenia, czy ta referencja wskazuje na coś, co istnieje), a PHP przed 5.5 nie obsługiwał referencji do wartości tymczasowych zwracanych z funkcji.

Jednak prawdziwym problemem jest to, że empty()w ogóle go używasz , błędnie wierząc, że „pusta” wartość różni się od „fałszywej”.

Pusty to tylko alias !isset($thing) || !$thing. Kiedy rzecz, którą sprawdzasz, zawsze istnieje (w PHP zawsze istnieją wyniki wywołań funkcji), empty()funkcja jest tylko operatorem negacji .

PHP nie ma pojęcia pustki . Wartości, które mają wartość false, są puste, wartości, które mają wartość true, są niepuste. To jest to samo. Ten kod:

$x = something();
if (empty($x)) 

i to:

$x = something();
if (!$x) 

ma zawsze ten sam wynik we wszystkich przypadkach dla wszystkich typów danych (ponieważ $xjest zdefiniowany empty()jest nadmiarowy).

Zwracana wartość z metody zawsze istnieje (nawet jeśli nie masz returninstrukcji, zwracana wartość istnieje i zawiera null). W związku z tym:

if (!empty($r->getError()))

jest logicznie równoważne z:

if ($r->getError())

29
Jest to znacznie lepsza odpowiedź niż obecnie wybrana.
SystemParadox

20
@gcb: nie, instrukcja PHP wyraźnie mówi, że jest identyczna: „empty () jest przeciwieństwem (boolean) var, z wyjątkiem tego, że nie jest generowane ostrzeżenie, gdy zmienna nie jest ustawiona”.
Kornel,

16
Nie generowanie części ostrzegawczej jest bardzo ważne ... puste ($ var) zwróci wartość true, jeśli jest równe 0, '', array (), NULL lub nawet nie jest zdefiniowane. Jest to dobra praktyka, szczególnie, abyś mógł rejestrować swoje prawdziwe ostrzeżenia bez wypełniania się plików
landons

3
Ok, świetna odpowiedź, ale jaki jest właściwy sposób, aby tego uniknąć, czy ktoś wie?
Javatar,

3
@EugenMihailescu w ogóle to jest OK, ale nie jest to ściśle równoważne empty (), ponieważ "", 0itp są „puste”, ale nie zerowa.
Kornel,

330

Uwaga: Jest to bardzo wysoko głosowana odpowiedź z dużą widocznością, ale należy pamiętać, że promuje złe, niepotrzebne praktyki kodowania! Prawidłowy sposób zobacz odpowiedź @ Kornela .

Uwaga 2: Popieram sugestie dotyczące użycia odpowiedzi @ Kornel . Kiedy napisałem tę odpowiedź trzy lata temu, chciałem jedynie wyjaśnić naturę błędu, niekoniecznie popierając alternatywę. Poniższy fragment kodu nie jest zalecany.


Jest to ograniczenie funkcji empty () w wersjach PHP poniżej 5.5.

Uwaga: empty () sprawdza tylko zmienne, ponieważ wszystko inne spowoduje błąd analizy. Innymi słowy, następujące funkcje nie będą działać: puste (przycinanie (nazwa $)).

Musisz to zmienić

// Not recommended, just illustrates the issue
$err = $r->getError();
if (!empty($err))

156
Jest to obłędnie bezproduktywne.
David Murdoch,

47
Uwaga: to samo dotyczy isset(). tzn .: isset($this->foo->getBar())spowoduje ten sam problem.
catchdave

7
Odpowiedź porneL wyjaśnia to bardziej szczegółowo, z lepszym rozwiązaniem
SystemParadox

5
@SystemParadox - Zależy od tego, co rozumiesz przez „lepszy”. Odpowiedź porneL jest prawdopodobnie dokładniejsza dzięki „czystszemu” rozwiązaniu, ale również nie wyjaśnia przyczyny błędu.
Peter Bailey,

4
Ponieważ to nie jest złe, @deceze. To nie jest najlepsza odpowiedź, nie dostaniesz ode mnie żadnych argumentów. Sam nawet głosowałem na porneL. To bardzo stara odpowiedź, ale nie jest zła . Jeśli chodzi o wysokie głosy: pamiętaj, że porneL dotarło prawie pełne 17 miesięcy po tym.
Peter Bailey,

37

Według dokumentów PHP :

empty () sprawdza tylko zmienne, ponieważ wszystko inne spowoduje błąd analizy

Nie można użyć empty()bezpośrednio na wartości zwracanej przez funkcję. Zamiast tego ustaw return from getError()na zmienną i uruchom empty()na zmiennej.


19

Zwykle tworzę funkcję globalną o nazwie is_empty (), aby obejść ten problem

function is_empty($var)
{ 
 return empty($var);
}

Wtedy gdziekolwiek normalnie użyłbym pustego () Po prostu używam is_empty ()


2
Lepiej tego nie robić i trzymać się standardów (choć irytujące).
tonyhb

1
@dynamism czy możesz wyjaśnić, dlaczego nie?
Janis Veinbergs,

1
Ponieważ funkcje wygody mogą utrudniać czytanie kodu innej osoby. Ponadto w architekturze MVC / HMVC może popsuć strukturę. Pod koniec dnia koderzy PHP powinni wiedzieć o swoich ograniczeniach i być w stanie zrozumieć małe obejścia bez funkcji wygody.
tonyhb

14
Wow, właśnie wymyśliłeś funkcję negacji . Wiesz, że PHP ma !do tego operatora? :)
Kornel,

4

Jak zauważyli inni, jest to (dziwne) ograniczenie pustych ().

W przypadku większości purproses zrobienie tego jest równoznaczne z wywołaniem pustego, ale działa to:

if ($r->getError() != '')

5
To nie jest prawda - empty()obejmuje o wiele więcej możliwości niż tylko pusty ciąg
Robbie Averill,

3
Dlatego mówi „dla większości celów ”, nie wszystkie
Jani Hartikainen,

2

Problem polega na tym, że chcesz wiedzieć, czy błąd nie jest pusty.

public function getError() {
    return $this->error;
}

Dodanie metody isErrorSet () rozwiąże problem.

public function isErrorSet() {
    if (isset($this->error) && !empty($this->error)) {
        return true;
    } else {
        return false;
    }
}

Teraz będzie działać dobrze z tym kodem bez powiadomienia.

if (!($x->isErrorSet())) {
    echo $x->getError();
}

-3

Alternatywnym sposobem sprawdzenia, czy tablica jest pusta, może być:

count($array)>0

Działa dla mnie bez tego błędu

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.