Różnica między "negowaniem" zmiennej a skorzystaniem z isset()

0

Przykładowy kod:

  public static function getInstance() {
    if (!self::$instance) { 
    [...]

To jest znaleziony gdzieś w necie przykładowy fragment implementacji singletona w PHP.
Pytanie jest takie - czemu ktoś dał !self zamiast !isset()?
Zamiana na isset() nic nie zmienia, całość działa tak samo jak z negującym wykrzyknikiem.
Czym się te dwa zapisy różnią? Który jest lepszy? Której wersji lepiej się trzymać?

Wszelkie uwagi i komentarze mile widziane ;)

1

Podobne się rozważa w JS (podwójne negacje)

jeśli rozumiem chodzi o to, ze jest burdel z kompatybilnością wszelkich możliwych typów z FALSE a zwłaszcza TRUE.
Twórcy języka / programiści już sami nie są pewni, co jest co, i używają j/w, po takich negacjach mają zagwarantowany typ boolean (coś co javowcy/sihaszwcy mają zapewnione z mocy ustawy)

1

Znalazłem w necie jeszcze takie coś, co może rzucić nowe światło na sprawę:

if we use directly !$variableName and the $variableName is not defined before that check, then a Undefined variable warning will be generated by php. If we use isset, then if the variable is defined before, then it is set the isset will return true, if not defined then isset will return false, and hence no Undefined Variable or index warning will be generated.

https://stackoverflow.com/questions/18763705/why-would-a-person-want-to-use-isset-over-just-variablename

1

Jeśli rzeczywiście nie ma jakiejś różnicy to użyłbym isset(); W tym przypadku to może być jednak pole tej klasy o dowolnym przeznaczeniu ... i co wtedy? Nie rozumiem tego. Może brkuje szerszego kontekstu?
Ogólnie nie lubię takich składniowych wygibasów. Na pierwszy rzut oka nie mam pojęcia o co chodzi i zmusza mnie to do nadmiernego wytężania umysłu podczas czytania kodu - w tym przypadku nawet to nic nie daje bo nadal nie mam pojęcia o co chodzi.
Zresztą w PHP8 ten kod i tak jest do du... więc nie ma co dalej drążyć :-)

Jeśli już faktycznie muszę użyć jakiejś sztuczki tego typu to odpowiednio komentuję ten fragment albo ubieram go w funkcję z nazwą, która nie wzbudza wątpliwości i wrzucam do biblioteki p.t. "Tools" i po kłopocie.

<?php

class Dupa{
  
  public static $instance = true ;
  public static function getInstance() {
    if (!self::$instance) {
      echo "getDupa?" ;
    } else {
      echo "Nie getDupa?" ;
    }
  }
  
}

Dupa::getInstance();
$aDupa = new Dupa();
$aDupa->getInstance();
0

Zresztą w PHP8 ten kod i tak jest do du...

@katakrowa: możesz rozwinąć ta myśl? Co wersja 8 ma do tego?

1
cerrato napisał(a):

Zresztą w PHP8 ten kod i tak jest do du...

@katakrowa: możesz rozwinąć ta myśl? Co wersja 8 ma do tego?

screenshot-20220816095115.png

0

OK, teraz rozumiem co miałeś na myśli.
Tak - odwołanie się do nieistniejącego pola static rzuci errora.
Ale w takim razie ponawiam pytanie - czy (i dlaczego) lepiej jest dawać !$dupa albo isset($dupa)?

3
cerrato napisał(a):

OK, teraz rozumiem co miałeś na myśli.
Tak - odwołanie się do nieistniejącego pola static rzuci errora.
Ale w takim razie ponawiam pytanie - czy (i dlaczego) lepiej jest dawać !$dupa albo isset($dupa)?

Ja osobiście nie używałbym żadnego z nich, z kilku powodów.

  • isset() po prostu robi za dużo, zbyt dużo jest rzeczy które mogą wpłynąć na jej wynik, przez w gruncie rzeczy to czy isset() zwróci false czy true mówi nam niewiele, nie specjalnie jest to użyteczne, isset() bierze pod uwagę pola obiektów, atrybuty klas, klucze w array, same zmienne, atrybutu atrybutów też, oraz bierze pod uwagę samą wartość, np null. Dodatkowo isset() wycisza wszystkie "nieistniejące" rzeczy, przez co jak napiszesz tam literówkę, to nie dostaniesz żadnego errora.
  • Co do if (!self::$instance), tego również nie używam, dlatego że taki zapis najpierw castuje zmienną na bool (co już w PHP jest powalone, za głowę się można złapać jakie są zasady castowania wartości na bool - np string "0" jest castowany na false. WTF!), a potem go odwraca. Także dla mnie to niej jest w ogóle opcja.

Ja sugeruję w ogóle w PHP nie robić takich rzeczy jak "sprawdzanie, czy coś istnieje w PHP", chyba że nie masz innego wyjścia.

A jeśli już musisz, to użyłbym jednego z tych zapisów:

  • self::$instance === null - koniecznie ===, nie ==
  • self::$instance === false
  • array_key_exists($array, 'key')
  • property_exists($object, 'property') - to jest dobre, bo nawet jeśli property ma null, to dostaniemy true (nie tak jak isset()).

Jeśli chcesz napisać singletona, to ja raczej użyłbym self::$instance === null. Ale singletona też bym raczej nie używał :D

PS: @cerrato Co do błędów w PHP, to jest trochę bardziej posrane, niż w innych językach. Mamy:

  • Parse error - aplikacja includowany/requireowany/uruchamiany plik nawet się nie włączy
  • Fatal error, kiedy się stanie proces PHP się po prostu ubija bez wysłania response'a. Nie da się tego niczym złapać, ani zareagować na to. Fatal to już koniec.
  • Exception - to jest jedyna normalna rzecz
  • Error, warning, notice - nie różnią się niczym od siebie - to jest taki dziwny mechanizm informowania o błędach, ale nie jest rzetelny, tzn ustawiana jest flaga, którą różne servery ogarniają inaczej (np rethrowują exception, printują błąd w HTML'u lub plaintexcie), i innych rzeczach
  • Niektóre błędy są po prostu wyciszane
  • Niektóre funkcje zwracają 0, false, -1 lub null jako "sygnał" o błędzie
  • Niektóre funkcje się "udają", ale błąd trzeba odczytać inną funkcją, np preg_last_error(), json_last_error(), mysql_error(), curl_error().

Także, z tymi błędami to nie jest takie czarno białe, a dodatkowo - PHP w różny sposób, różną "siłą" reaguje na różne błędy, np:

PHP hehe:

  • Użycie nieistniejącego property, np $user->idd - warning
  • Użycie nieistniejącego consta, np USER_IDD - notice
  • Użycie propery na czymś, co nie jest obiektem, np ([1,2,3])->property - notice
  • Użycie nieistniejącej zmiennej - notice
  • Iterowanie po czymś co nie jest arrayem, np po integer - warning

PHP not hehe:

  • Użycie niestniejącego statica - Fatal error?
  • Użycie stringa jako call funkcji - parse error
  • Użycie niestniejącej funkcji - fatal error
  • Użycie isset() (lub echo, list(), die()i innych "konstruktów") jako funkcji - parse error

Wyjątków nie rzuca praktycznie nic w PHP, może oprócz najnowszych feature'ów w PHP.

0

@Riddle: dzięki za fajną i wyczerpującą odpowiedź.

Skoro zamiast isset() proponujesz (co zresztą ma sens) zapis ===null to co masz do powiedzenia na w kwestii zwalniania zmiennych - czy lepiej dać unset() czy $dupa = null? Z tego co widzę, w necie zdania są podzielone, ja bym się skłaniał raczej w kierunku unset(), ale może Ty proponujesz inną opcję?

https://www.geeksforgeeks.org/which-one-is-better-unset-or-var-null-to-free-memory-in-php/
https://stackoverflow.com/questions/13667137/the-difference-between-unset-and-null

0
cerrato napisał(a):

@Riddle: dzięki za fajną i wyczerpującą odpowiedź.

Skoro zamiast isset() proponujesz (co zresztą ma sens) zapis ===null to co masz do powiedzenia na w kwestii zwalniania zmiennych - czy lepiej dać unset() czy $dupa = null? Z tego co widzę, w necie zdania są podzielone, ja bym się skłaniał raczej w kierunku unset(), ale może Ty proponujesz inną opcję?

https://www.geeksforgeeks.org/which-one-is-better-unset-or-var-null-to-free-memory-in-php/
https://stackoverflow.com/questions/13667137/the-difference-between-unset-and-null

Ja w swoich programach nigdy nie zwalniam zmiennych, więc unset(), nigdy nie używam. Nie mam w swoich programach kodu który sprawdza istnienie jakiejś zmiennej bądź property, jeśli w jakimś kodzie używam zmiennej, to dbam o to, by w tym momencie była zdefiniowana (czyli muszę swoją dyscypliną pilnować to co robi za mnie kompilator jak np w Javie lub c#).

Jeśli zaś chodzi o ustalenie $var = null;, to nie widzę w tym specjalnego sensu, jako jakąś idea "usuwania zmiennych". Jeśli już coś, to może jako forma czyszczenia stanu w kolekcji lub cache'u, ale raczej nie.

Nie martwię się o performance wynikający z ze zmiennych, mam małe funkcje więc u mnie zmienne żyją raczej krótko więc i tak będą wyczyszczone po wyjściu z funkcji.

1 użytkowników online, w tym zalogowanych: 0, gości: 1