Créer un objet par défaut à partir d'une valeur vide en PHP?


362

Je vois cette erreur uniquement après la mise à niveau de mon environnement PHP vers PHP 5.4 et au-delà. L'erreur pointe vers cette ligne de code:

Erreur:

Création d'un objet par défaut à partir d'une valeur vide

Code:

$res->success = false;

Dois-je d'abord déclarer mon $resobjet?


11
Comment / où commencez-vous $res ?
Naveed

1
@NAVEED .
7heo.tk

Réponses:


627

Votre nouvel environnement peut avoir des E_STRICTavertissements activés dans leserror_reporting versions PHP <= 5.3.x, ou simplement avoir error_reportingdéfini au moins E_WARNINGavec les versions PHP> = 5.4. Cette erreur est déclenchée lorsqu'elle $resest NULLou non encore initialisée:

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

PHP signalera un message d'erreur différent s'il $resest déjà initialisé à une certaine valeur mais n'est pas un objet:

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

Afin de se conformer aux E_STRICTnormes antérieures à PHP 5.4, ou au E_WARNINGniveau d'erreur normal dans PHP> = 5.4, en supposant que vous essayez de créer un objet générique et d'assigner la propriété success, vous devez déclarer $resen tant qu'objet de stdClassdans l'espace de noms global:

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

38
Vous vérifier si l'devraient objet existe déjà: if (!isset($res)) $res = new stdClass();. Sinon, ce code n'est pas un remplacement équivalent à la création d'objet implicite "ancien PHP".
TMS

6
@Tomas Faut-il recommencer? Les mods ont nettoyé le fil de commentaires la dernière fois car il n'a ajouté que peu de valeur. Il n'y a pas de création d'objet implicite "vieux PHP". C'était toujours une erreur et toujours émis un avertissement, juste qu'il était passé de E_STRICT à E_WARNING en 5.4, donc certaines personnes ne l'ont jamais rencontré sans avoir prêté attention à E_STRICT.
Michael Berkowski

4
@PeterAlfvin, il n'a pas été défini dans cette exécution particulière ! Mais dans une exécution différente, exactement au même endroit dans le code , l'objet peut être déjà défini! C'est une erreur de penser que les gens font souvent et c'est la raison pour laquelle j'essaie de le souligner.
TMS

2
Michael, la création implicite d'objets a toujours été et est toujours présente même en 5.4. Et BTW En PHP <5.3, ce n'était ni E_STRICT ni E_WARNING. Et BTW, les mods ont restauré le commentaire et on m'a dit de l'atténuer, c'est pourquoi je l'ai republié.
TMS

3
@tomas Oh, ok, je pense avoir compris ce que tu veux dire. Il semble étrange que vous / Michael ne puissiez pas conclure. BTW, cet échange m'a amené à réaliser que les italiques <bold <allcaps en termes de "force" et que si allcaps = shouting et italics = politeEmphasis, bold est dans un milieu où l'acceptabilité est discutable. :-)
Peter Alfvin

57

Ce message E_STRICTconcerne PHP <= 5.3. Depuis PHP 5.4, il a malheureusement été remplacé par E_WARNING. Étant donné que les E_WARNINGmessages sont utiles, vous ne voulez pas les désactiver complètement.

Pour vous débarrasser de cet avertissement, vous devez utiliser ce code:

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

$res->success = false;

Il s'agit d' un remplacement entièrement équivalent . Il assure exactement la même chose que PHP fait silencieusement - malheureusement avec un avertissement maintenant - la création implicite d'objets. Vous devez toujours vérifier si l'objet existe déjà, à moins que vous ne soyez absolument sûr qu'il ne l'est pas. Le code fourni par Michael n'est pas bon en général, car dans certains contextes, l'objet peut parfois être déjà défini au même endroit dans le code, selon les circonstances.


2
@carlosvini, cela vous donnera Undefined variable: res.
Pacerier

1
@Pacerier Vous avez raison, le mieux que vous puissiez faire est: $ res = isset ($ res)? $ res: new stdClass (); - c'est la raison pour laquelle je n'ai pas activé E_NOTICE il y a 6 mois, car il est trop verbeux.
carlosvini

13

Simplement,

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

Ou vous pouvez instancier des cours avec:

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

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

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

et remplissez les valeurs avec:

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

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

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

Plus d'infos: https://www.php.net/manual/en/language.types.object.php#language.types.object.casting


pourquoi la nouvelle stdClass () est-elle considérée comme une "ancienne" méthode? Les autres sont-ils en quelque sorte meilleurs?
Aaron

C'est simplement de l'ancienne version php
pirs

dans mon cas $this->route->uri = new stdClass();ne fonctionne pas pour moi, j'ai toujours l'avertissement. Remarque: $this->routeexiste.
Meloman

Peut-être que ce n'est pas compatible avec les nouvelles versions de php? Quelle version avez-vous utilisée?
pir

6

Si vous mettez le caractère "@" au début de la ligne, PHP n'affiche aucun avertissement / avis pour cette ligne. Par exemple:

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

Pour éviter cet avertissement pour cette ligne, vous devez mettre le caractère "@" au début de la ligne comme ceci:

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

J'utilise cette astuce lors du développement. Je n'aime pas désactiver tous les messages d'avertissement car si vous ne gérez pas correctement les avertissements, ils deviendront une grosse erreur à l'avenir.


1
@ empêche les avertissements en le supprimant, semble correct tant que vous avez du code gérable. Mais si votre code devient quelque chose de plus gros et que vous rencontrez un problème, vous regretterez en quelque sorte de l'utiliser. Vous vous retrouverez à rechercher tous ces "@" pour un avertissement que vous voudriez afficher, car temporairement il a atteint son objectif en pensant que vous avez réellement résolu le problème alors qu'en réalité il vous a parlé et que vous ne le voudriez pas ' t écoute.
Vincent Edward Gedaria Binua

Je sais déjà. C'est une réponse courte et rapide. Il existe de nombreuses solutions pour cela.
kodmanyagha

2
impressionnant! Puis-je poliment demander à être en désaccord, cacher l'erreur ne résout pas vraiment le problème (comme l'a également commenté Ramy Nasr).
Vincent Edward Gedaria Binua

Cette solution de contournement est le seul workin pour moi sur php 7.2.
Meloman

3

Essayez ceci si vous avez un tableau et ajoutez-y des objets.

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

Cela envoie un tableau d' objets pour une utilisation ultérieure ~!


1
MERCI!!!! C'est ce qui a aidé à faire le travail. Je devais dire à PHP étape par étape ce qu'était chaque élément. Merci de me rappeler de ne pas coder lazy lol.
yanike

2

Essaye ça:

ini_set('error_reporting', E_STRICT);

1
Merci. c'est une utilisation complète lorsque vous utilisez des bibliothèques tierces telles que nusoap et que vous ne voulez / ne pouvez pas changer la source. Dans ce cas, vous pouvez modifier error_reporting au niveau E_STRICT juste avant d'exiger d'autres fichiers source.
mtoloo

Bien que je viens d'ajouter cela en haut de nusoap pour résoudre mon problème.
badweasel

11
Hein? Le code ici désactive tous les rapports d' E_STRICTerreurs à l' exception des erreurs, y compris la suppression des messages pour les erreurs fatales. Ce n'est pas une suggestion raisonnable pour résoudre cet avertissement particulier, et de plus, c'est quelque chose que vous ne voulez presque jamais faire. Pourquoi 5 personnes ont voté pour cela, je n'en ai aucune idée.
Mark Amery

1
C'est super mauvais! utiliser ini_set('error_reporting', -1);lors du débogage, mais n'utilisez pas ce qui précède, comme jamais.
Kzqai

Ok, donc vous corrigez un problème en cachant celui-ci? Pas sûr que votre code fonctionnera comme prévu ...
pirs

1

J'ai eu un problème similaire et cela semble résoudre le problème. Vous avez juste besoin d'initialiser l'objet $ res à une classe. Supposons ici que le nom de la classe est test.

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

1

C'est un avertissement auquel j'ai été confronté en PHP 7, la solution la plus simple consiste à initialiser la variable avant de l'utiliser

$myObj=new \stdClass();

Une fois que vous l'avez initialisé, vous pouvez l'utiliser pour des objets

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

0

Ce problème est dû au fait que vous attribuez à une instance d'objet qui n'est pas initiée. Par exemple:

Ton cas:

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

Solution:

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

ne supposez-vous pas que la classe "User" existe? ce qu'il ne peut pas et maintenant il va générer une erreur différente?
Christopher Thomas

1
En fait, je n'ai pas créé d'instance de l'objet User, j'ai donc reçu une erreur. Mais après avoir créé une instance. Cela a fonctionné .. c'est un problème générique avec le concept des POO :)
Bastin Robin

6
eh bien, en fait, le vrai problème est que votre exemple suppose que la classe d'utilisateurs à définir, ce n'est pas un problème générique d'orientation d'objet, c'est une exigence clé;)
Christopher Thomas

1
Je préfère mettre un "stdClass" générique remplaçant la prémisse impliquant "User".
TechNyquist

0

Un moyen simple d'obtenir cette erreur consiste à taper (a) ci-dessous, c'est-à-dire à taper (b)

(une) $this->my->variable

b) $this->my_variable

Trivial, mais très facilement négligé et difficile à repérer si vous ne le recherchez pas.


Quel est le lien avec la question d'origine? Il n'y avait pas de confusion entre _et->
Nico Haase

0

Vous devrez peut-être vérifier si la variable est déclarée et a un type correct.

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;

Voir les classes anonymes PHP .


0

J'ai eu un problème similaire en essayant d'ajouter une variable à un objet renvoyé par une API. Je parcourais les données avec une boucle foreach.

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

Cela a déclenché l'exception «Création d'un objet par défaut à partir d'une valeur vide» dans Laravel.

Je l'ai corrigé avec un tout petit changement.

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

En faisant simplement de $ data une référence.

J'espère que cela aide quelqu'un à me gêner!


0
  1. Pensez d'abord à créer un objet $ res = new \ stdClass ();

  2. puis affectez l'objet avec la clé et la valeur thay $ res-> success = false;


(Je ne comprends pas thay.) Lorsque vous souhaitez un saut de ligne après certains contenus, ajoutez deux espaces vides au contenu visible de la ligne avant le saut.
greybeard

-1

non vous ne le faites pas .. il le créera lorsque vous ajouterez la valeur de succès à l'objet. la classe par défaut est héritée si vous n'en spécifiez pas une.


4
Bien qu'il renverra le message des normes strictes ... c'est tout simplement une bonne pratique de créer l'objet manuellement d'abord, et bien que PHP soit relativement tolérant à la pratique de codage de mauvaise qualité, vous ne devriez pas ignorer faire les choses correctement.
Mark Baker

4
compris, je répondais simplement à la question par un simple oui ou non, ne définissant pas ou ne défendant pas les meilleures pratiques :)
Silvertiger

-1

Essayez d'utiliser:

$user = (object) null;

2
Généralement, les réponses sont beaucoup plus utiles si elles incluent une explication de ce que le code est censé faire et pourquoi cela résout le problème sans en introduire d'autres.
lucascaro

-12

J'ai mis ce qui suit en haut du fichier PHP défaillant et l'erreur ne s'affichait plus:

error_reporting(E_ERROR | E_PARSE);
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.