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?


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;

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.


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


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.


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 ~!


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

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;

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;

0

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

Twój przypadek:

$user->email = 'exy@gmail.com';

Rozwiązanie:

$user = new User;
$user->email = 'exy@gmail.com';

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.


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 .


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!


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;


(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.


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;

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