432

I see this error only after upgrading my PHP environment to PHP 5.4 and beyond. The error points to this line of code:

Error:

Creating default object from empty value

Code:

$res->success = false;

Do I first need to declare my $res object?

Michael Berkowski
  • 267,341
  • 46
  • 444
  • 390
Paul
  • 11,671
  • 32
  • 91
  • 143

18 Answers18

745

Your new environment may have E_STRICT warnings enabled in error_reporting for PHP versions <= 5.3.x, or simply have error_reporting set to at least E_WARNING with PHP versions >= 5.4. That error is triggered when $res is NULL or not yet initialized:

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

PHP will report a different error message if $res is already initialized to some value but is not an object:

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

In order to comply with E_STRICT standards prior to PHP 5.4, or the normal E_WARNING error level in PHP >= 5.4, assuming you are trying to create a generic object and assign the property success, you need to declare $res as an object of stdClass in the global namespace:

$res = new \stdClass();
$res->success = false;
Michael Berkowski
  • 267,341
  • 46
  • 444
  • 390
  • @Tomas Of course you may need to check, but that isn't relevant to the question. This is about how to properly instantiate a `stdClass`. It is the responsibility of the developer to be sure an existing object or scalar isn't being overwritten if the variable already exists. – Michael Berkowski Nov 20 '13 at 14:16
  • 48
    You shoud check whether the object already exists: `if (!isset($res)) $res = new stdClass();`. Otherwise, this code is not an equivalent replacement for the "old PHP" implicit object creation. – Tomas Nov 23 '13 at 15:44
  • 6
    @Tomas Do we need to do this again? The mods cleaned up the comment thread last time because it added little of value. There is no "old PHP" implicit object creation. It was always an error and always issued a warning, just that it was changed from E_STRICT to E_WARNING in 5.4, so some people never encountered it not having paid attention to E_STRICT. – Michael Berkowski Nov 23 '13 at 15:51
  • @Tomas I'm no PHP expert, but given the error the OP reported, don't you know that `$res` is undefined in this case, thus eliminating the need for the check you're proposing? – Peter Alfvin Nov 23 '13 at 15:51
  • @PeterAlfvin Interesting, thanks. I wondered what sparked this. – Michael Berkowski Nov 23 '13 at 16:00
  • 5
    @PeterAlfvin it was not defined **in that one particular run**! But in different run, *at the exact same place in the code*, the object might be already defined! This is mistake in thinking people often make and that's the reason I try to emphasize that. – Tomas Nov 23 '13 at 16:10
  • 2
    Michael, the implicit object creation always was and is still present even in 5.4. And BTW In PHP < 5.3 it was neither E_STRICT nor E_WARNING. And BTW, mods have restored the comment and I was told to tone it down, that's why I re-posted it. – Tomas Nov 23 '13 at 16:13
  • 3
    @tomas Oh, ok, I _think_ I get what you mean. It seems odd that you/Michael can't get to closure on this. BTW, this exchange has led me to realize that italics – Peter Alfvin Nov 23 '13 at 16:19
  • Why do you use `$res = new stdClass();` instead of the shorter version `$res = new stdClass;`? – Pacerier Jan 30 '15 at 19:48
  • @Pacerier It is a matter of style. Use whatever is your team's agreed-upon convention. I always use them because I don't like class constructors without args to be treated differently than those with, and I don't want `stdClass` to be treated differently than any class I define myself. [Here you will find one suggestion, then the opposite suggestion in a linked duplicate](http://stackoverflow.com/questions/9325491/when-to-add-brackets-after-new-class-name). It's only up to style. – Michael Berkowski Jan 30 '15 at 19:53
  • @Pacerier [And another](http://stackoverflow.com/questions/3873111/instantiate-a-class-with-or-without-parentheses) `stdClass` calls no constructor, so if you don't want to think of it like a method call, omit the `()`. I would not omit them though for consistency with userdef classes – Michael Berkowski Jan 30 '15 at 19:55
  • @MichaelBerkowski, Well, omit them and still have consistency with userdef classes by omitting them in userdef classes too. – Pacerier Jan 30 '15 at 20:23
  • @Pacerier No, that's inconsistent between classes which have constructor params and those which do not. It doesn't matter- this is a question of opinion and style and I'm not going to argue it in the comments. – Michael Berkowski Jan 30 '15 at 20:25
  • This grammar is very confusing. "Your new environment may have E_STRICT warnings enabled in error_reporting if it is PHP <= 5.3, or if simply have error_reporting set to at least E_WARNING with PHP 5.4+. – ahnbizcad Feb 23 '18 at 18:05
  • In my case, i spelt the object variable wrongly. Watch out for that! – Ayo Makanjuola Oct 18 '18 at 20:00
67

This message has been E_STRICT for PHP <= 5.3. Since PHP 5.4, it was unluckilly changed to E_WARNING. Since E_WARNING messages are useful, you don't want to disable them completely.

To get rid of this warning, you must use this code:

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

$res->success = false;

This is fully equivalent replacement. It assures exactly the same thing which PHP is silently doing - unfortunatelly with warning now - implicit object creation. You should always check if the object already exists, unless you are absolutely sure that it doesn't. The code provided by Michael is no good in general, because in some contexts the object might sometimes be already defined at the same place in code, depending on circumstances.

Tomas
  • 57,621
  • 49
  • 238
  • 373
  • 2
    @carlosvini, This will give you `Undefined variable: res`. – Pacerier Jan 26 '15 at 12:49
  • 1
    @Pacerier You are right, the best you can do is: $res = isset($res) ? $res : new stdClass(); -- which was the reason i didn't have E_NOTICE enabled 6 months ago, since it's too damn verbose. – carlosvini Jan 26 '15 at 13:48
18

Simply,

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

Or you could instantiate classes with:

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

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

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

and fill values with:

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

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

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

More infos: https://www.php.net/manual/en/language.types.object.php#language.types.object.casting

pirs
  • 2,410
  • 2
  • 18
  • 25
8

If you put "@" character begin of the line then PHP doesn't show any warning/notice for this line. For example:

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

For preventing this warning for this line you must put "@" character begin of the line like this:

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

I'm using this trick when developing. I don't like disable all warning messages becouse if you don't handle warnings correctly then they will become a big error in future.

kodmanyagha
  • 932
  • 12
  • 20
  • 3
    @ does prevent warnings by suppressing it, looks ok for as long as you have manageable code. But if your code grows into something bigger and you ran into an issue, you'll somehow regret using this. You'll find yourself looking for all those "@" for a warning you'd want to unhide because temporarily it has served its purpose thinking that you have actually fixed the issue when in reality it has been talking to you and you just wouldn't listen. – Vincent Edward Gedaria Binua Jul 29 '17 at 08:59
  • I know already. This is short and fast answer. There are lots of solution for this. – kodmanyagha Jul 29 '17 at 10:48
  • 3
    awesome! May I politely beg to disagree though, hiding the error is not really fixing the problem (as what Ramy Nasr commented as well). – Vincent Edward Gedaria Binua Jul 29 '17 at 11:16
  • This workaround is the only workin for me on php 7.2. – Meloman Jan 03 '20 at 07:15
6

Try this if you have array and add objects to it.

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

This sends ARRAY of Objects for later use~!

Develop4Life
  • 7,581
  • 8
  • 58
  • 76
  • 1
    THANK YOU!!!! This is what helped get the job done. I needed to tell PHP step-by-step what each element was. Thanks for reminding me not to code lazy lol. – yanike Jun 11 '20 at 18:59
4

In PHP 7 anonymous objects can be created this way:

$res = new class {
    public $success = false;
};

https://www.php.net/manual/en/language.oop5.anonymous.php http://sandbox.onlinephpfunctions.com/code/ab774707a8219c0f35bdba49cc84228b580b52ee

bancer
  • 7,475
  • 7
  • 39
  • 58
2
  1. First think you should create object $res = new \stdClass();

  2. then assign object with key and value thay $res->success = false;

  • (I don't understand `thay`.) Where you want a line break after some contents, append two blank spaces to the visible contents of the line before the break-to-be. – greybeard Apr 28 '20 at 09:20
1

Try this:

ini_set('error_reporting', E_STRICT);
Irfan
  • 4,882
  • 12
  • 52
  • 62
  • 1
    Thanks. this is use full when you are using third-party libraries such as nusoap and don't want / can't change the source. In that case you can change error_reporting to **E_STRICT** level just before requiring other source files. – mtoloo Dec 23 '13 at 16:20
  • Although I just added this to the top of nusoap to fix my problem. – badweasel Aug 19 '14 at 20:25
  • 11
    Huh? The code here disables all error reporting except `E_STRICT` errors, including suppressing messages for fatal errors. That's not a reasonable suggestion to solve this particular warning, and what's more is something you pretty much never ever want to do. Why 5 people upvoted this, I have no clue. – Mark Amery Sep 29 '14 at 23:37
  • 1
    This is super bad! use `ini_set('error_reporting', -1);` while debugging, but don't use the above, like ever. – Kzqai Dec 30 '16 at 21:42
  • Ok, so you fix a problem by hiding this one ? Not sure your code will work as expected... – pirs Jan 12 '20 at 10:46
1

I had similar problem and this seem to solve the problem. You just need to initialize the $res object to a class . Suppose here the class name is test.

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

Starting from PHP 7 you can use a null coalescing operator to create a object when the variable is null.

$res = $res ?? new \stdClass();
$res->success = false;
Florian Rival
  • 601
  • 4
  • 11
Lost user
  • 11
  • 3
0

A simple way to get this error is to type (a) below, meaning to type (b)

(a) $this->my->variable

(b) $this->my_variable

Trivial, but very easily overlooked and hard to spot if you are not looking for it.

mega6382
  • 9,211
  • 17
  • 48
  • 69
Tannin
  • 65
  • 3
0

You may need to check if variable declared and has correct type.

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;

See PHP anonymous classes.

Anton Pelykh
  • 2,274
  • 1
  • 18
  • 21
0

Try using:

$user = (object) null;
Fischer Tirado
  • 321
  • 3
  • 5
  • 2
    Generally, answers are much more helpful if they include an explanation of what the code is intended to do, and why that solves the problem without introducing others. – lucascaro Nov 09 '18 at 06:45
0

I had a similar problem while trying to add a variable to an object returned from an API. I was iterating through the data with a foreach loop.

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

This threw the "Creating default object from empty value" Exception in Laravel.

I fixed it with a very small change.

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

By simply making $data a reference.

I hope that helps somebody a it was annoying the hell out of me!

Andy
  • 333
  • 4
  • 10
-1

This problem is caused because your are assigning to an instance of object which is not initiated. For eg:

Your case:

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

Solution:

$user = new User;
$user->email = 'exy@gmail.com';
Bastin Robin
  • 907
  • 16
  • 30
-1

This is a warning which I faced in PHP 7, the easy fix to this is by initializing the variable before using it

$myObj=new \stdClass();

Once you have intialized it then you can use it for objects

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

no you do not .. it will create it when you add the success value to the object.the default class is inherited if you do not specify one.

Silvertiger
  • 1,680
  • 2
  • 19
  • 32
  • 4
    Though it will return the Strict standards message... it is simply good practise to create the object manually first, and while PHP is relatively tolerant of shoddy coding practise, you shouldn't ignore doing things correctly. – Mark Baker Jan 17 '12 at 19:49
  • 4
    understood, i was just answering the question with a simple yes or no, not defining or defending best practices :) – Silvertiger Jan 17 '12 at 19:54
-12

I put the following at the top of the faulting PHP file and the error was no longer display:

error_reporting(E_ERROR | E_PARSE);
Doug
  • 5,116
  • 10
  • 33
  • 42