12

Well I'm really confused. When i check if a property exists it returns false.

if (property_exists($pais, 'id'))
// false

but when I debug it shows me it's there.

print_r($pais->id);
// 1
print_r(property_exists($pais, 'id'));
// false

Am I crazy or my neurons just fried?

and the creation of pais is done by

if (key_exists('country', $data))
    $pais = Pais::adicionarPais($data);

(...) 

public static function adicionarPais(array $data)
{
    return Pais::firstOrCreate(['nome' => $data['country']]);
}
Danilo Kobold
  • 2,562
  • 1
  • 21
  • 31

4 Answers4

15

I see you're using Laravel, so I guess this are Eloquent models. They're probably using magic methods to create dynamic properties and methods from your database columns. Take a look here: http://php.net/manual/en/language.oop5.overloading.php

So, instead of having real properties, every time you request a property, they will check if there's any column or relationship and return that instead.

You can get your model attributes with the getAttributes() method (https://github.com/illuminate/database/blob/master/Eloquent/Concerns/HasAttributes.php#L851)

class Pais
{
    public function __get($name) {
        if ($name == 'id') {
            return 1;
        }
    }
}
$pais = new Pais();
var_dump($pais->id); // int(1)
var_dump(property_exists($pais, 'id')); // bool(false)
fedeisas
  • 1,991
  • 2
  • 22
  • 34
7

You can convert the model to an array and then use array_key_exists. Eloquent object properties are set via magic methods, so property_exists will not work, especially if the property actually does exist but is set to null.

Example:

$pais = Pais::find(1);

if (array_key_exists('country', $pais->toArray())) {
    // do stuff
}

Note the use of toArray on the model.

kjdion84
  • 9,552
  • 8
  • 60
  • 87
1

I'm using Laravel and had the same issue.

The $this->getAttributes() in combination with property_exists() doesn't work, because property_exists() only works on objects and Classes, so you need isset() or array_key_exists().

The problem with isset() is that if the key exists but the value is null it returns false, so it's not the same as property_exists(). The array_key_exists() does behave like property_exists() but is deprecated since PHP 7.4.

Solution: Cast the Array as an Object, and use property_exists():

property_exists((object)$this->getAttributes(), $key)

Frank Boon
  • 31
  • 1
0

No need to go through it all and then if you are diligent and want to check what getAttributes or toArray Laravel functions return and what happens, we can use a combination of isset and is_null PHP core functions. I am concentrating here on Laravel and corresponding relationsip which is a bit of a more complex example but all the other variants can be extracted from below code. Enjoy and I hope it will save time. Let me try to elaborate with full proof Laravel example and Artisan Tinker.

Please bear with me.

Thank you PHP Artisan Tinker!

/**
 * @return \Illuminate\Database\Eloquent\Model|HasMany|object|null
 */
public function profile(): HasMany
{
    return $this->hasMany(User_profile::class, 'user_id', 'user_id')
        ->orderBy('created_at', 'desc');
}
php artisan tinker

>>> $u = (new App\Models\User())->find(11549)
=> App\Models\User {#3481
     user_id: 11549,
     created_at: "2019-10-31 09:26:14",
     updated_at: "2019-10-31 09:26:14",
     first_name: "Pippy",
     middle_name: null,
     last_name: "Longstocking",
     phone: null,
     email: "11544@example.com",
     pincode: null,
     flag_is_active: 0,
     flag_is_email_subscribed: 1,
     flag_is_mobile_subscribed: 1,
     flag_terms_agreed: 1,
     flag_is_blocked: 0,
     flag_delete: 0,
     where_from: 1,
     employee_status: 0,
     remember_token: null,
     user_reference: "11544",
     alternate_user_reference: "11544",
     user_transaction_reference: null,
     user_channel: null,
     campaign_id: 0,
     ip_address: "172.31.10.23",
   }

>>> $u->profile()
=> Illuminate\Database\Eloquent\Relations\HasMany {#3483}

>>> $userProfile=$u->profile()->first();
=> null

>>> $userProfile->flag_ifisa
PHP Notice:  Trying to get property 'flag_ifisa' of non-object in Psy Shell code on line 1

>>> $userProfile->toArray()
PHP Error:  Call to a member function toArray() on null in Psy Shell code on line 1

>>> $userProfile->getAttributes()
PHP Error:  Call to a member function getAttributes() on null in Psy Shell code on line 1

>>> is_null($userProfile)
=> true

>>> isset($userProfile->flag_ifisa)
=> false

Matija
  • 17,604
  • 2
  • 48
  • 43