Creazione di un oggetto predefinito da un valore vuoto in PHP?


362

Vedo questo errore solo dopo aver aggiornato il mio ambiente PHP a PHP 5.4 e versioni successive. L'errore punta a questa riga di codice:

Errore:

Creazione di un oggetto predefinito da un valore vuoto

Codice:

$res->success = false;

Devo prima dichiarare il mio $resoggetto?


11
Come / dove stai iniziando $res ?
— Naveed

1
@NAVEED There .
— 7heo.tk,

Risposte:


627

Il tuo nuovo ambiente potrebbe avere gli E_STRICTavvisi abilitatierror_reporting per le versioni di PHP <= 5.3.x, o semplicemente aver error_reportingimpostato almeno E_WARNINGcon le versioni di PHP> = 5.4. Tale errore viene attivato quando $resè NULLo non è ancora inizializzato:

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

PHP segnalerà un messaggio di errore diverso se $resè già inizializzato su un valore ma non è un oggetto:

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

Per rispettare gli E_STRICTstandard precedenti a PHP 5.4 o il normale E_WARNINGlivello di errore in PHP> = 5.4, supponendo che si stia tentando di creare un oggetto generico e assegnare la proprietà success, è necessario dichiarare $rescome oggetto stdClassnello spazio dei nomi globale:

$res = new \stdClass();
$res->success = false;

38
Si shoud verificare se l'oggetto esiste già: if (!isset($res)) $res = new stdClass();. Altrimenti, questo codice non è un sostituto equivalente per la creazione implicita di "vecchio PHP".
— TMS

6
@Tomas Dobbiamo farlo di nuovo? Le mod hanno ripulito il thread dei commenti l'ultima volta perché ha aggiunto poco valore. Non esiste la creazione di oggetti impliciti "vecchio PHP". È sempre stato un errore e ha sempre emesso un avviso, solo che è stato cambiato da E_STRICT a E_WARNING in 5.4, quindi alcune persone non l'hanno mai incontrato non avendo prestato attenzione a E_STRICT.
— Michael Berkowski,

4
@PeterAlfvin non è stato definito in quella corsa particolare ! Ma in una corsa diversa, esattamente nello stesso posto nel codice , l'oggetto potrebbe essere già definito! Questo è un errore nel pensare che la gente faccia spesso ed è la ragione per cui provo a enfatizzarlo.
— TMS

2
Michael, la creazione implicita di oggetti è sempre stata ed è ancora presente anche in 5.4. E BTW In PHP <5.3 non era né E_STRICT né E_WARNING. E a proposito, le mod hanno ripristinato il commento e mi è stato detto di ridimensionarlo, ecco perché l'ho ripubblicato.
— TMS

3
@tomas Oh, ok, penso di capire cosa intendi. Sembra strano che tu / Michael non riesca a concludere questo. A proposito, questo scambio mi ha portato a capire che il corsivo <grassetto <tutti i tappi in termini di "forza" e che mentre tutti i tappi = urla e corsivo = educazione positiva, il grassetto si trova in una via di mezzo in cui l'accettabilità è discutibile. :-)
— Peter Alfvin,

57

Questo messaggio è stato E_STRICTper PHP <= 5.3. Da PHP 5.4, è stato purtroppo cambiato in E_WARNING. Poiché i E_WARNINGmessaggi sono utili, non si desidera disabilitarli completamente.

Per eliminare questo avviso, è necessario utilizzare questo codice:

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

$res->success = false;

Questa è una sostituzione completamente equivalente . Assicura esattamente la stessa cosa che PHP sta facendo silenziosamente - sfortunatamente con avvertimento ora - creazione implicita di oggetti. Dovresti sempre verificare se l'oggetto esiste già, a meno che tu non sia assolutamente sicuro che non lo sia. Il codice fornito da Michael non va bene in generale, perché in alcuni contesti l'oggetto a volte potrebbe essere già definito nello stesso posto nel codice, a seconda delle circostanze.


2
@carlosvini, questo ti darà Undefined variable: res.
— Pacerier,

1
@Pacerier Hai ragione, il meglio che puoi fare è: $ res = isset ($ res)? $ res: new stdClass (); - che era il motivo per cui non avevo abilitato E_NOTICE 6 mesi fa, dal momento che è troppo dannatamente dettagliato.
— carlosvini,

13

Semplicemente,

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

Oppure puoi istanziare le lezioni con:

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

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

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

e riempi i valori con:

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

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

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

Ulteriori informazioni: https://www.php.net/manual/en/language.types.object.php#language.types.object.casting


perché new stdClass () è considerato un metodo "vecchio"? Gli altri sono in qualche modo migliori?
— Aaron,

È semplicemente dalla vecchia versione di php
— pirs

nel mio caso $this->route->uri = new stdClass();non funziona per me, ho ancora l'avvertimento. Nota: $this->routeesiste.
— Meloman,

Forse questo non è compatibile con le nuove versioni di php? Quale versione hai usato?
— pirs

6

Se inserisci il carattere "@" all'inizio della riga, PHP non mostra alcun avviso / avviso per questa riga. Per esempio:

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

Per evitare questo avviso per questa riga è necessario inserire il carattere "@" all'inizio della riga in questo modo:

@$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

Sto usando questo trucco durante lo sviluppo. Non mi piace disabilitare tutti i messaggi di avviso perché se non gestisci correttamente gli avvisi, in futuro diventeranno un grosso errore.


1
@ previene gli avvisi reprimendolo, sembra ok fintanto che si dispone di codice gestibile. Ma se il tuo codice diventa qualcosa di più grande e hai riscontrato un problema, in qualche modo ti pentirai di averlo usato. Ti ritroverai a cercare tutti quei "@" per un avvertimento che vorresti scoprire perché temporaneamente ha funzionato allo scopo pensando di aver effettivamente risolto il problema quando in realtà ti ha parlato e non volevi ' ascolta.
— Vincent Edward Gedaria Binua,

Lo so già. Questa è una risposta breve e veloce. Ci sono molte soluzioni per questo.
— Kodmanyagha,

2
eccezionale! Posso educatamente supplicare di non essere d'accordo, nascondere l'errore non risolve davvero il problema (come ha commentato anche Ramy Nasr).
— Vincent Edward Gedaria Binua,

Questa soluzione alternativa è l'unica soluzione per me su PHP 7.2.
— Meloman,

3

Prova questo se hai array e aggiungi oggetti ad esso.

$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.
}

Questo invia ARRAY di oggetti per un uso successivo ~!


1
GRAZIE!!!! Questo è ciò che ha contribuito a portare a termine il lavoro. Avevo bisogno di dire passo dopo passo a PHP quale fosse ciascun elemento. Grazie per avermi ricordato di non codificare Lazy Lol.
— yanike,

2

Prova questo:

ini_set('error_reporting', E_STRICT);

1
Grazie. questo è pieno quando usi librerie di terze parti come nusoap e non vuoi / non puoi cambiare l'origine. In tal caso, è possibile modificare la segnalazione degli errori al livello E_STRICT appena prima di richiedere altri file di origine.
— mtoloo,

Anche se l'ho appena aggiunto all'inizio di nusoap per risolvere il mio problema.
— badweasel,

11
Eh? Il codice qui disabilita tutti i rapporti sugli E_STRICTerrori tranne gli errori, inclusa la soppressione dei messaggi per errori irreversibili. Non è un suggerimento ragionevole per risolvere questo particolare avvertimento, e per di più è qualcosa che praticamente non vorresti mai fare. Perché 5 persone hanno votato questo, non ne ho idea.
— Mark Amery,

1
Questo è super male! utilizzare ini_set('error_reporting', -1);durante il debug, ma non utilizzare quanto sopra, come sempre.
— Kzqai,

Ok, quindi risolvi un problema nascondendo questo? Non che il codice funzionerà come previsto ...
— Pirs

1

Ho avuto un problema simile e questo sembra risolvere il problema. Devi solo inizializzare l'oggetto $ res in una classe. Supponiamo che il nome della classe sia test.

class test
{
   //You can keep the class empty or declare your success variable here
}
$res = new test();
$res->success = false;

1

Questo è un avvertimento che ho affrontato in PHP 7, la soluzione semplice a questo è inizializzando la variabile prima di usarla

$myObj=new \stdClass();

Dopo averlo inizializzato, è possibile utilizzarlo per gli oggetti

 $myObj->mesg ="Welcome back - ".$c_user;

0

Questo problema è causato dal fatto che si sta assegnando a un'istanza di oggetto che non è stata avviata. Ad esempio:

Il tuo caso:

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

Soluzione:

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

non stai supponendo che esista la classe "Utente"? quale potrebbe non essere e ora genererà un errore diverso?
— Christopher Thomas,

1
In realtà non ho creato un'istanza dell'oggetto Utente, quindi ho ricevuto un errore. Ma dopo aver creato un'istanza. Ha funzionato .. è un problema generico con il concetto di OOP :)
— Bastin Robin,

6
bene, in realtà il vero problema è che il tuo esempio presuppone che sia definita la classe utente, questo non è un problema generico di orientamento agli oggetti, è un requisito chiave;)
— Christopher Thomas

1
Preferirei inserire una "stdClass" generica in sostituzione della premessa che implica "Utente".
— TechNyquist,

0

Un modo semplice per ottenere questo errore è digitare (a) di seguito, ovvero digitare (b)

(un) $this->my->variable

(B) $this->my_variable

Triviale, ma molto facilmente trascurato e difficile da individuare se non lo stai cercando.


In che modo ciò è legato alla domanda originale? Non ci fu confusione tra _e->
— Nico Haase,

0

Potrebbe essere necessario verificare se la variabile è stata dichiarata e ha il tipo corretto.

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;

Vedi lezioni anonime PHP .


0

Ho avuto un problema simile durante il tentativo di aggiungere una variabile a un oggetto restituito da un'API. Stavo ripetendo i dati con un ciclo foreach.

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

Ciò ha generato l'eccezione "Creazione di un oggetto predefinito da un valore vuoto" in Laravel.

L'ho risolto con un piccolo cambiamento.

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

Semplicemente facendo $ dati un riferimento.

Spero che questo aiuti qualcuno che mi ha dato fastidio!


0
  1. Innanzitutto pensa che dovresti creare l'oggetto $ res = new \ stdClass ();

  2. quindi assegnare l'oggetto con chiave e valore thay $ res-> success = false;


(Non capisco thay.) Dove vuoi un'interruzione di riga dopo alcuni contenuti, aggiungi due spazi vuoti ai contenuti visibili della riga prima dell'inizio del futuro.
— greybeard,

-1

no non lo fai .. lo creerà quando aggiungi il valore di successo all'oggetto. la classe predefinita viene ereditata se non ne specifichi uno.


4
Anche se restituirà il messaggio sugli standard rigorosi ... è semplicemente una buona pratica creare prima l'oggetto manualmente, e mentre PHP è relativamente tollerante con la pratica scadente del codice, non dovresti ignorare di fare le cose correttamente.
— Mark Baker,

4
capito, stavo solo rispondendo alla domanda con un semplice sì o no, non definendo o difendendo le migliori pratiche :)
— Silvertiger

-1

Prova a usare:

$user = (object) null;

2
In generale, le risposte sono molto più utili se includono una spiegazione di ciò che il codice è destinato a fare e perché risolve il problema senza introdurre altri.
— lucascaro,

-12

Ho messo quanto segue nella parte superiore del file PHP in errore e l'errore non veniva più visualizzato:

error_reporting(E_ERROR | E_PARSE);
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.