Backend Development

PHP Access Objects As Arrays Using The ArrayAccess Interface

PHP Access Objects As Arrays Using The ArrayAccess Interface

One of the important interfaces in PHP, which enables us to access the elements of a class as an array manner which is the ArrayAccess interface.

 

 

 

Unlike the used methods when accessing class properties using the arrow -> symbol, PHP provides the ArrayAccess interface. When you implement this interface you must implement the 4 methods provided by the interface as shown in the interface terminology below:

 interface ArrayAccess {
    /* Methods */
    public offsetExists(mixed $offset): bool
    public offsetGet(mixed $offset): mixed
    public offsetSet(mixed $offset, mixed $value): void
    public offsetUnset(mixed $offset): void
}

As shown in the interface structure there four methods, offsetExists(), offsetGet(), offsetSet(), offsetUnset(). These methods triggered automatically when trying to set a property as an array, check property exists with isset() function and unsetting property using unset() function.

But let’s see first if we have a class like this:

class Container
{
    public $property = 1;
}

To use and access the property in this class:

$obj = new Container();
echo $obj->property;   // 1

If we attempt to access the property like an array it will trigger an error:

echo $obj['property'];

// output
Fatal error: Uncaught Error: Cannot use object of type Container as array

Now by modifying the class to implement the ArrayAccess interface like this:

class Container implements ArrayAccess
{
   public $property = 1;
}

This time when running the script it show this error:

PHP Fatal error:  Class Container contains 4 abstract methods and must therefore be declared abstract or implement the remaining methods (ArrayAccess::offsetExists, ArrayAccess::offsetGet, ArrayAccess::offsetSet, ...)

This error because it request from us that we must implement the four methods that i stated above.

Let’s see how can we implement this interface:

class Container implements ArrayAccess
{
    private $data = [];

    public function offsetSet($offset, $value)
    {
        echo "\n offsetSet triggered<br/>\n";

        if (is_null($offset)) {
            $this->data[] = $value;
        } else {
            $this->data[$offset] = $value;
        }
    }

    public function offsetExists($offset)
    {
        echo "\n offsetExists triggered<br/>\n";

        return isset($this->data[$offset]);
    }

    public function offsetUnset($offset)
    {
        echo "\n offsetUnset triggered<br/>\n";

        unset($this->data[$offset]);
    }

    public function offsetGet($offset)
    {
        echo "\n offsetGet triggered<br/>\n";

        return isset($this->data[$offset]) ? $this->data[$offset] : null;
    }
}

In this code i added a private $data property, then in each of the methods all you have to do is to write and read in the $data property. For example the offsetSet($offset, $value) typically this method writes to the $data array using the passed $offset and $value.

I added an echo statement in each method to see when those methods got triggered in the client code.

$container = new Container();

$container['property1'] = 1;
$container['property2'] = 2;
$container['property3'] = 3;

echo $container['property2'] . "\n";
echo (isset($container['property3']) ? 'yes' : 'no') . "\n";

unset($container['property1']);
echo (isset($container['property1']) ? 'yes' : 'no') . "\n";

$container[] = "John";
$container[] = "Acme";

var_dump($container);

// output

offsetSet triggered<br/>
 offsetSet triggered<br/>
 offsetSet triggered<br/>
 offsetGet triggered<br/>
2
 offsetExists triggered<br/>
yes
 offsetUnset triggered<br/>
 offsetExists triggered<br/>
no
 offsetSet triggered<br/>
 offsetSet triggered<br/>
object(Container)#1 (1) {
  ["data":"Container":private]=>
  array(4) {
    ["property2"]=>
    int(2)
    ["property3"]=>
    int(3)
    [0]=>
    string(4) "John"
    [1]=>
    string(4) "Acme"
  }
}

As shown that the methods triggered at certain points:

  • When adding new item in the object using $container[‘property’] = 1 the offsetSet() triggered
  • When retrieving an item from the object like echo $container[‘property2’] the offsetGet() triggered.
  • When checking for existence of property in the object using isset() the offsetExists() triggered.
  • When removing property using unset() function the offsetUnset() triggered.

 

Someone might ask this is familiar, in fact there is a feature in php oop that seem similar to this which is the magic methods. Yes that’s right there are some magic methods like __set(), __get, __isset() which also triggered automatically. But these methods fired when you access a property using the arrow -> symbol like so:

$obj->property

But what’s the point of accessing an object as an array?

Some frameworks and libraries provides accessing properties in different ways using the traditional arrow -> symbol and the array syntax. Examples in laravel and symfony frameworks the ArrayAccess is mostly used.

0 0 votes
Article Rating

What's your reaction?

Excited
0
Happy
0
Not Sure
0
Confused
0

You may also like

Subscribe
Notify of
guest

0 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments