Tworzysz domyślny obiekt z pustej wartości w PHP?

362

Widzę ten błąd dopiero po zaktualizowaniu środowiska PHP do wersji PHP 5.4 i nowszych. Błąd wskazuje na ten wiersz kodu:

Błąd:

Tworzenie domyślnego obiektu z pustej wartości

Kod:

$res->success = false;

Czy najpierw muszę zadeklarować swój $resobiekt?

Paweł
źródło
11
Jak / gdzie inicjujesz $res ?
Naveed,
1
@NAVEED Tam .
7heo.tk

Odpowiedzi:

627

W nowym środowisku może być włączoneE_STRICT ostrzeżenia dla wersji PHP <= 5.3.x lub po prostu ustawione na przynajmniej wersje PHP> = 5.4. Ten błąd jest wyzwalany, gdy jest lub nie jest jeszcze zainicjowany:error_reportingerror_reportingE_WARNING$resNULL

$res = NULL;
$res->success = false; // Warning: Creating default object from empty value

PHP zgłosi inny komunikat o błędzie, jeśli $resjest już zainicjowany na jakąś wartość, ale nie jest obiektem:

$res = 33;
$res->success = false; // Warning: Attempt to assign property of non-object

Aby zachować zgodność ze E_STRICTstandardami wcześniejszymi niż PHP 5.4 lub normalnym E_WARNINGpoziomem błędu w PHP> = 5.4, zakładając, że próbujesz utworzyć obiekt ogólny i przypisać właściwość success, musisz zadeklarować $resjako obiekt stdClassw globalnej przestrzeni nazw:

$res = new \stdClass();
$res->success = false;
Michał Berkowski
źródło
38
Ty powinien sprawdzić, czy obiekt już istnieje: if (!isset($res)) $res = new stdClass();. W przeciwnym razie ten kod nie jest równoważnym zamiennikiem niejawnego tworzenia obiektów „starego PHP”.
TMS
6
@Tomas Czy musimy to zrobić ponownie? Mody ostatnio wyczyściły wątek komentarza, ponieważ nie dodały żadnej wartości. Nie ma niejawnego tworzenia „starego PHP”. Zawsze był to błąd i zawsze wyświetlał ostrzeżenie, po prostu zmieniono go z E_STRICT na E_WARNING w 5.4, więc niektóre osoby nigdy go nie spotkały, nie zwracając uwagi na E_STRICT.
Michael Berkowski
4
@PeterAlfvin nie został zdefiniowany w tym konkretnym przebiegu ! Ale w innym przebiegu, dokładnie w tym samym miejscu w kodzie , obiekt może być już zdefiniowany! To błąd w myśleniu, że ludzie często popełniają i dlatego staram się to podkreślać.
TMS
2
Michael, niejawne stworzenie obiektu zawsze było i jest obecne nawet w 5.4. A BTW W PHP <5.3 to nie był ani E_STRICT, ani E_WARNING. A BTW, mody przywróciły komentarz i kazano mi go stonować, dlatego ponownie go opublikowałem.
TMS
3
@tomas Oh, ok, myślę, że rozumiem o co ci chodzi. Wydaje się dziwne, że ty / Michael nie jesteś w stanie tego zakończyć. Przy okazji, ta wymiana sprawiła, że ​​zdałem sobie sprawę, że kursywa <pogrubienie <allcaps pod względem „siły” i że podczas gdy allcaps = krzyczenie i kursywa = grzeczność Podkreślenie, pogrubienie znajduje się na środku, gdzie akceptowalność jest wątpliwa. :-)
Peter Alfvin,
57

Ta wiadomość E_STRICTdotyczy PHP <= 5.3. Od PHP 5.4 zmieniono to na nieszczęście E_WARNING. Ponieważ E_WARNINGwiadomości są przydatne, nie chcesz ich całkowicie wyłączać.

Aby pozbyć się tego ostrzeżenia, musisz użyć tego kodu:

if (!isset($res)) 
    $res = new stdClass();

$res->success = false;

Jest to w pełni równoważna wymiana . Zapewnia dokładnie to samo, co PHP cicho robi - niestety teraz z ostrzeżeniem - niejawne tworzenie obiektów. Zawsze powinieneś sprawdzić, czy obiekt już istnieje, chyba że masz absolutną pewność, że nie istnieje. Kod dostarczony przez Michaela nie jest ogólnie dobry, ponieważ w niektórych kontekstach obiekt może czasami być już zdefiniowany w tym samym miejscu kodu, w zależności od okoliczności.

TMS
źródło
2
@carlosvini, To da ci Undefined variable: res.
Pacerier
1
@Pacerier Masz rację, najlepsze, co możesz zrobić, to: $ res = isset ($ res)? $ res: new stdClass (); - z tego powodu 6 miesięcy temu nie włączyłem E_NOTICE, ponieważ jest to zbyt cholernie gadatliwe.
carlosvini
13

Po prostu,

    $res = (object)array("success"=>false); // $res->success = bool(false);

Lub możesz utworzyć instancję zajęć za pomocą:

    $res = (object)array(); // object(stdClass) -> recommended

    $res = (object)[];      // object(stdClass) -> works too

    $res = new \stdClass(); // object(stdClass) -> old method

i wypełnij wartości:

    $res->success = !!0;     // bool(false)

    $res->success = false;   // bool(false)

    $res->success = (bool)0; // bool(false)

Więcej informacji: https://www.php.net/manual/en/language.types.object.php#language.types.object.casting

pirowie
źródło
dlaczego nowa metoda stdClass () jest uważana za „starą” metodę? Czy inni są jakoś lepsi?
Aaron
Jest po prostu ze starej wersji php
pirs
w moim przypadku $this->route->uri = new stdClass();nie działa dla mnie, nadal mam ostrzeżenie. Uwaga: $this->routeistnieje.
Meloman
Może to nie jest kompatybilne z nowymi wersjami php? Której wersji użyłeś?
pirs
6

Jeśli umieścisz znak „@” na początku wiersza, PHP nie wyświetli żadnego ostrzeżenia / powiadomienia dla tego wiersza. Na przykład:

$unknownVar[$someStringVariable]->totalcall = 10; // shows a warning message that contains: Creating default object from empty value

Aby zapobiec ostrzeżeniu dla tego wiersza, należy umieścić znak „@” na początku wiersza w następujący sposób:

@$unknownVar[$someStringVariable]->totalcall += 10; // no problem. created a stdClass object that name is $unknownVar[$someStringVariable] and created a properti that name is totalcall, and it's default value is 0.
$unknownVar[$someStringVariable]->totalcall += 10; // you don't need to @ character anymore.
echo $unknownVar[$someStringVariable]->totalcall; // 20

Używam tej sztuczki podczas programowania. Nie lubię wyłączać wszystkich komunikatów ostrzegawczych, ponieważ jeśli nie będziesz obsługiwał ostrzeżeń poprawnie, w przyszłości staną się one dużym błędem.

kodmanyagha
źródło
1
@ zapobiega ostrzeżeniom poprzez ich wyłączenie, wygląda dobrze, dopóki masz zarządzalny kod. Ale jeśli Twój kod urosnie w coś większego i napotkasz problem, z jakiegoś powodu będziesz tego żałować. Będziesz szukał wszystkich „@” dla ostrzeżenia, które chciałbyś odkryć, ponieważ chwilowo spełniło swoje zadanie, myśląc, że naprawiłeś problem, podczas gdy w rzeczywistości rozmawia z tobą, a ty po prostu nie chcesz słuchaj.
Vincent Edward Gedaria Binua
Już wiem. To krótka i szybka odpowiedź. Istnieje na to wiele rozwiązań.
kodmanyagha
2
niesamowite! Pozwólcie, że grzecznie zacznę się nie zgadzać, ukrywanie błędu tak naprawdę nie naprawia problemu (jak to również skomentował Ramy Nasr).
Vincent Edward Gedaria Binua
To obejście jest dla mnie jedynym działaniem na PHP 7.2.
Meloman
3

Spróbuj tego, jeśli masz tablicę i dodaj do niej obiekty.

$product_details = array();

foreach ($products_in_store as $key => $objects) {
  $product_details[$key] = new stdClass(); //the magic
  $product_details[$key]->product_id = $objects->id; 
   //see new object member created on the fly without warning.
}

Ten wysyła ARRAY z obiektami w celu późniejszego użycia ~!

Daniel Adenew
źródło
DZIĘKUJĘ CI!!!! To właśnie pomogło w wykonaniu pracy. Musiałem powiedzieć PHP krok po kroku, jaki był każdy element. Dzięki za przypomnienie, żebym nie kodował leniwego lola.
yanike
2

Spróbuj tego:

ini_set('error_reporting', E_STRICT);
Irfan
źródło
1
Dzięki. jest to pełne, gdy korzystasz z bibliotek innych firm, takich jak nusoap i nie chcesz / nie możesz zmienić źródła. W takim przypadku możesz zmienić raportowanie błędów na poziom E_STRICT tuż przed wymaganiem innych plików źródłowych.
mtoloo,
Chociaż właśnie dodałem to na górze nusoap, aby naprawić mój problem.
badweasel,
11
Co? Tutaj kod wyłącza wszystkie raporty o E_STRICTbłędach oprócz błędów, w tym pomijanie komunikatów o błędach krytycznych. To nie jest rozsądna sugestia, aby rozwiązać to szczególne ostrzeżenie, a ponadto jest to coś, czego prawie nigdy nie chcesz robić. Dlaczego 5 osób głosowało za tym, nie mam pojęcia.
Mark Amery
1
To bardzo źle! używaj ini_set('error_reporting', -1);podczas debugowania, ale nie używaj powyższych, jak zawsze.
Kzqai
Ok, więc rozwiązujesz problem, ukrywając ten? Nie jestem pewien, czy Twój kod będzie działał zgodnie z oczekiwaniami ...
pirs,
1

Miałem podobny problem i to wydaje się rozwiązać problem. Musisz tylko zainicjować obiekt $ res w klasie. Załóżmy, że tutaj nazwa klasy to test.

class test
{
   //You can keep the class empty or declare your success variable here
}
$res = new test();
$res->success = false;
Kevin Stephen Biswas
źródło
1

Jest to ostrzeżenie, z którym spotkałem się w PHP 7, łatwym rozwiązaniem jest zainicjowanie zmiennej przed użyciem

$myObj=new \stdClass();

Po zainicjowaniu możesz go używać do obiektów

 $myObj->mesg ="Welcome back - ".$c_user;
Ayan Bhattacharjee
źródło
0

Przyczyną tego problemu jest przypisanie do instancji obiektu, który nie został zainicjowany. Na przykład:

Twój przypadek:

$user->email = '[email protected]';

Rozwiązanie:

$user = new User;
$user->email = '[email protected]';
Bastin Robin
źródło
nie zakładasz, że istnieje klasa „Użytkownik”? co może nie, a teraz wygeneruje inny błąd?
Christopher Thomas
1
W rzeczywistości nie utworzyłem instancji obiektu użytkownika, więc wystąpił błąd. Ale po utworzeniu instancji. Udało się ... to ogólny problem z koncepcją OOP :)
Bastin Robin
6
no cóż, w rzeczywistości prawdziwym problemem jest to, że twój przykład zakłada zdefiniowanie klasy użytkownika, nie jest to ogólny problem orientacji obiektu, to kluczowy wymóg;)
Christopher Thomas
1
Wolę umieścić ogólną „stdClass”, zastępując przesłankę implikującą „Użytkownik”.
TechNyquist
0

Prostym sposobem na uzyskanie tego błędu jest wpisanie poniżej (a), co oznacza wpisanie (b)

(za) $this->my->variable

(b) $this->my_variable

Trywialne, ale bardzo łatwe do przeoczenia i trudne do wykrycia, jeśli go nie szukasz.

Tanina
źródło
Jak to się ma do pierwotnego pytania? Tam nie było mieszać się pomiędzy _i->
Nico Haase
0

Może być konieczne sprawdzenie, czy zmienna została zadeklarowana i ma poprawny typ.

if (!isset($res) || !is_object($res)) {
    $res = new \stdClass();
    // With php7 you also can create an object in several ways.
    // Object that implements some interface.
    $res = new class implements MyInterface {};
    // Object that extends some object.
    $res = new class extends MyClass {};
} 

$res->success = true;

Zobacz anonimowe klasy PHP .

Anton Pelykh
źródło
0

Miałem podobny problem podczas próby dodania zmiennej do obiektu zwróconego z interfejsu API. Iterowałem dane za pomocą pętli foreach.

foreach ( $results as $data ) {
    $data->direction = 0;
}

To spowodowało wyjątek „Tworzenie domyślnego obiektu z pustej wartości” w Laravel.

Naprawiłem to z bardzo małą zmianą.

foreach ( $results as &$data ) {
    $data->direction = 0;
}

Po prostu czyniąc dane $ odniesieniem.

Mam nadzieję, że to komuś pomaga, to mnie denerwowało!

Andy
źródło
0
  1. Najpierw pomyśl, że powinieneś utworzyć obiekt $ res = new \ stdClass ();

  2. następnie przypisz obiekt kluczem i wartością thay $ res-> success = false;

Sukron Ma'mun
źródło
(Nie rozumiem thay.) Jeśli chcesz, aby podział linii po jakiejś zawartości, dodaj dwie puste spacje do widocznej zawartości linii przed przerwą.
Greybeard
-1

nie, nie ... utworzy ją, gdy dodasz wartość obiektu do obiektu. klasa domyślna zostanie odziedziczona, jeśli jej nie określisz.

Silvertiger
źródło
4
Chociaż zwróci komunikat Ścisłe standardy ... po prostu dobrą praktyką jest ręczne utworzenie obiektu, a chociaż PHP jest stosunkowo tolerancyjny wobec tandetnej praktyki kodowania, nie powinieneś ignorować robienia rzeczy poprawnie.
Mark Baker
4
zrozumiałem, właśnie odpowiadałem na pytanie tylko tak lub nie, nie definiując ani nie broniąc najlepszych praktyk :)
Silvertiger
-1

Spróbuj użyć:

$user = (object) null;
Fischer Tirado
źródło
2
Zasadniczo odpowiedzi są o wiele bardziej pomocne, jeśli zawierają wyjaśnienie, do czego służy kod i dlaczego rozwiązuje problem bez przedstawiania innych.
lucascaro,
-12

Umieściłem następujące na górze pliku PHP powodującego błąd i błąd nie był już wyświetlany:

error_reporting(E_ERROR | E_PARSE);
Doug
źródło