1

I am studying how array_column works and I have read that if applying this function to an array of objects whose properties are private/protected, an implementation of both __get and __isset is needed. But I don't understand why __isset is used when __get itself can access these properties.

<?php

class Person{
    private $name;

    public function __construct(string $name)
    {
        $this->name = $name;
    }

    public function __get($prop)
    {
        return $this->$prop;
    }

    public function __isset($prop) : bool
    {
        return isset($this->$prop);
    }
}

$people = [
    new Person('Fred'),
    new Person('Jane'),
    new Person('John'),
];

print_r(array_column($people, 'name'));
?>

I have found this related question, but I didn't find an answer.

Boann
  • 48,794
  • 16
  • 117
  • 146
Mohamed Omar
  • 453
  • 5
  • 16
  • Because: 1. `__get()` on an un-set property will generate a notice, but just return NULL, and you're going to want to avoid that situation most times. 2. If your getters and setters use something more complex than object properties to store information you will need more complex `__isset()` logic. – Sammitch Apr 04 '18 at 18:25
  • What if i am sure that the property isset and removed the __isset, i will get an empty array – Mohamed Omar Apr 04 '18 at 18:35

2 Answers2

2

After some thinking, i have found what convinces me, which is that the array_column function applies the isset function on each property, which needs the __isset magic method to be implemented into the class to be called whenever isset() is called on a protected/private property

Mohamed Omar
  • 453
  • 5
  • 16
0

The objects using __get do not require __isset.

The array_column function use __isset to check if should fetch private or protected property.

The point of using __isset prior to __get is to ensure that it should fetch existing property value.

It's equivalent of checking array value before using it:

// Initialize array with not fully expected data
$myArray = getValues();
if(isset($myArray['myColumn']))
{
    echo $myArray['myColumn'];
}

In your example class php would do for each Person instance something like this internally:

if($persion->__isset('name'))
{
    return $person->__get('name');
}

NOTE: Using isset($this->$prop) is a bad idea, as it will return false on null value!

Use property_exists instead, ie:

public function __isset($prop) : bool
{
    return property_exists($this, $prop);
}
PeterM
  • 1,478
  • 1
  • 22
  • 28