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.