PHPs predefined ArrayAccess interface and ArrayObject class: How objects acts like arrays

Muhammad Anwar Hussain
4 min readJul 24, 2019

--

Object Oriented Programming: PHPs built-in ArrayAccess interface and ArrayObject class

PHP ships with a number of predefined classes and interfaces, two of the common out of them are ArrayAccess interface and ArrayObject class. Specially, these two can be very handy whenever objects requires the features of arrays. According to PHP documentation, if a class implements ArrayAccess then objects of that class can be accessed as we access arrays. On the other hand, a class that extends ArrayObject, objects of that class work as arrays.

The ArrayAccess interface has four abstract methods, which are ArrayAccess::offsetExists, ArrayAccess::offsetSet, ArrayAccess::offsetGet, and ArrayAccess::offsetUnset. Now, somebody may ask the question: what is an abstract method? A method that does not obtain any implementation, more specifically, a method that does not hold a body, is known as abstract method . Thus each of these abstract methods further needs an implementation.

By default, ArrayObject class implements IteratorAggregate, ArrayAccess, Serializable and Countable interfaces. As a result, all abstract methods of these interfaces are already implemented by built-in ArrayObject class. Therefore, when we extend ArrayObject class by other classes, we may only need to override some of the methods from ArrayObject class. We will see the fact by the last example.

OK, let’s now talk about how to introduce the above features through our examples sequentially. Although it is not always be appropriate to use a Dependency Injection Container, but I am so obsessed about using DI Container through my last few articles that, all the examples I am going to introduce today are also based on DI Container. The article on DI container can be reached by this Link

Firstly, we will take an example whereby we intentionally produce some errors or notices for using PHPs unset() and shuffle()functions. Secondly, we will show how to mitigate the problems by implementing ArrayAccess interface by the Container class. In the final example, by extending ArrayObject class by the Container class, we will create objects that perform like arrays.

The examples below are mainly focused on the operations for implementing ArrayAccess and extending ArrayObject by the Container class:

  • flights_example.php
  • ArrayAccess.php
  • ArrayObject.php

At first I have constructed the Container class with the support of two PHP magic methods __set() and __get() which initially handle setting and getting properties for the Container object. One can find more details about these two methods by this Link. The motive of this example is that, I want to execute some regular flights via a number of terminals in a busy airport for performing all the specific tasks which are exclusively handled by the Container object. For that reason, I want to use unset()and shuffle() PHPs built-in functions to control the most recent flights from a flights schedules by the limited terminals in some random fashion. But the problem here is that, by the support of these __set() and __get() methods, the Container object is unable to perform the tasks unlike arrays which can be seen by the following snippet of code:

class Container
{
protected $data = array();

function __set($k, $v)
{
$this->data[$k] = $v;
}

function __get($k)
{
if (!isset($this->data[$k]))
{
throw new Exception(sprintf('Key "%s" does
not exists.', $k));
}
return is_callable($this->data[$k])? $this->data[$k]
($this) : $this->data[$k];
}
}

$c = new Container();

$c->flights = ['Flight_A', 'Flight_B', 'Flight_C', 'Flight_D',
'Flight_E'];
$c->terminals = ['Terminal_1', 'Terminal_2', 'Terminal_3'];

if(isset($c->flights[1]))
{
unset($c->flights[1]);
}

if(isset($c->flights[4]))
{
unset($c->flights[4]);
}

shuffle($c->flights);
shuffle($c->terminals);

In this case, when using unset() and shuffle() functions by the Container object, the program produces four notices as: "Indirect modification of overloaded property has no effect …". Through the 2nd example we will try to solve these problems.

It is mention able that if somebody eager to get more information about how these magic methods __set() and __get() work with the anonymous function shown here then please, visit the article by this Link.

Here is the full code for the first example:

The problem in the first example can be solved easily by implementing ArrayAccess interface by the Container class so that the Container object can be accessed as arrays. One fact about interfaces is that, they are great for telling you what methods you need to define, but less great at telling you what each method is supposed to do. So we need to define all these abstract methods based on what the objects demand in our application. If someone want to know more about interfaces, then he may visit this Link.

Here is the complete code for the 2nd example:

But there is a problem in the 2nd example with the following code:

for ($c['indx'] = 0; $c['indx'] < count($c['terminals']); $c['indx'] = $c['indx'] + 1)
{
//.....
}

If we look into the code above we can easily see that the Container object is unable to use increment or decrement operators because, until now, it does not have the feature to do such things. This and some other deficiencies can be solved by introducing ArrayObject built-in class into the Container. Therefore, in the last example, I have constructed the Container class by extending ArrayObject.

By the following example we have now completed the discussion:

By this article I have tried to focus on PHPs built-in ArrayAccess interface and ArrayObject class and further shown how create Container objects that work as arrays. Although, Container objects is still missing some of the functionalities of arrays, somehow we can manage them by doing some tricks. For example, by using a Container object we are still unable to access array-library-functions.

That’s all for Today! Next time I will come with another exciting feature of the PHP language.

Any of yours valuable comments and suggestions about the article beside your claps, would be greatly appreciated.

The PHP files for this topic and some of other related programming code can be found in my GitHub repository.

--

--