75

I get this warning in my error logs and wanted to know how to correct this issues in my code.

Warning: PHP Notice: Undefined property: stdClass::$records in script.php on line 440

Some Code:

// Parse object to get account id's
// The response doesn't have the records attribute sometimes.
$role_arr = getRole($response->records);  // Line 440 

Response if records exists

stdClass Object
(
    [done] => 1
    [queryLocator] =>
    [records] => Array
        (
            [0] => stdClass Object
                (
                    [type] => User
                    [Id] =>
                    [any] => stdClass Object
                        (
                            [type] => My Role
                            [Id] =>
                            [any] => <sf:Name>My Name</sf:Name>
                        )

                )

        )

    [size] => 1
)

Response if records does not exist

stdClass Object
(
    [done] => 1
    [queryLocator] =>
    [size] => 0
)

I was thinking something like array_key_exists() functionality but for objects, anything? or am I going about this the wrong way?

Phill Pafford
  • 83,471
  • 91
  • 263
  • 383
  • To explain, I've intentionally close this page with a more recent page. Though counter-intuitive on the surface, it is the recommended behavior on Stack Overflow to give greater priority to pages with better content versus trying to simply preserve the oldest page. – mickmackusa Jul 14 '21 at 05:43

8 Answers8

159
if(isset($response->records))
    print "we've got records!";
Orion
  • 1,104
  • 3
  • 16
  • 40
user187291
  • 53,363
  • 19
  • 95
  • 127
8

In this case, I would use:

if (!empty($response->records)) {
 // do something
}

You won't get any ugly notices if the property doesn't exist, and you'll know you've actually got some records to work with, ie. $response->records is not an empty array, NULL, FALSE, or any other empty values.

dazweeja
  • 334
  • 2
  • 3
8

isset() is fine for top level, but empty() is much more useful to find whether nested values are set. Eg:

if(isset($json['foo'] && isset($json['foo']['bar'])) {
    $value = $json['foo']['bar']
}

Or:

if (!empty($json['foo']['bar']) {
    $value = $json['foo']['bar']
}
markdwhite
  • 2,360
  • 19
  • 24
  • `if(isset($json['foo'] && isset($json['foo']['bar'])) {` is performing a needless check. Besides the fact that `isset()` could happily receive both of the variables in a single call, just check for the deeper element that you intend to access. `if(isset($json['foo']['bar'])) {` – mickmackusa Aug 23 '20 at 12:47
  • 1
    @mickmackusa - yeah. No idea why I had that opinion 6 years ago, but it is what it is. I don't think isset() changed behaviour from 5.X to current, but either way, what you say is correct. – markdwhite Jul 14 '21 at 05:19
  • @markdwhite I thought it worked the same as you tbh. Turns out it was changed in 5.4 to work the same. I guess we're old ;) – Paul Phillips Dec 07 '21 at 11:09
  • I agree that checking both is a needless case, but is you ever need to, you can use only one isset -> `isset($json['foo'], $json['bar'])` – Don Viegues Apr 28 '22 at 18:00
5

You can use property_exists
http://www.php.net/manual/en/function.property-exists.php

hacksy
  • 830
  • 5
  • 14
2

If you want to use property_exists, you'll need to get the name of the class with get_class()

In this case it would be :

 if( property_exists( get_class($response), 'records' ) ){
       $role_arr = getRole($response->records);
 }
 else
 {
       ...
 }
Mike Mackintosh
  • 13,917
  • 6
  • 60
  • 87
Astucieux
  • 149
  • 1
  • 7
2

Null Coalesce Operator

You can use the isset_ternary operator ??. This allows you to avoid warnings and assign default value in a short one line fashion.

$role_arr = getRole($response->records ?? null);

Error control operator

In case the warning is expected you can use the error control operator @ to suppress thrown messages.

$role_arr = getRole(@$response->records);

While this reduces clutter in your code you should use it with caution as it may make debugging future errors harder. An example where using @ may be useful is when creating an object from user input and running it through a validation method before using it in further logic.

Cray
  • 2,774
  • 7
  • 22
  • 32
  • 2
    1. I would never recommend the "stfu operator" (`@`) -- I never use it in my code because it indicates that a developer is lazily choosing not to properly handle a problem. 2. If `getRole()` expects to receive an iterable type value, then passing `null` is a bad idea -- without a deeper understanding of the application, it's probably wiser to fallback to `[]` (an empty array). That said, I definitely do support the recommendation of using the "null coalescing operator" (`??`). – mickmackusa Aug 23 '20 at 12:56
1

The response itself seems to have the size of the records. You can use that to check if records exist. Something like:

if($response->size > 0){
    $role_arr = getRole($response->records);
}
pinaki
  • 5,393
  • 2
  • 24
  • 32
  • This is the lightest / most direct approach if you only want to declare `$role_arr` if there are records to process. The `$response` object appears to unconditionally offer the `size` property, so use that and more on. Note that the same effect is achieved with `if ($response->size) {` since `0` is a falsey value. – mickmackusa Aug 23 '20 at 12:53
0

If think this will work:

if(sizeof($response->records)>0)
$role_arr = getRole($response->records);

newly defined proprties included too.

Melsi
  • 1,462
  • 1
  • 15
  • 21