Stop using Arrays

By Jean Hertel, 2/22/21

php , array

Today I want to talk about an extremely used data structure in PHP, the array. For those who don’t know, the PHP array is a very versatile data structure, it can store any kind of data due to the dynamic nature of PHP. Let’s look at some examples to understand the power of a PHP array.

Declaring an array:

<?php
// We can declare an empty array
$example = [];

// We can also initialize an array with values
$example = [
    1, 2, 3, 5, 8
];

// An array has dynamic size, so we can add as many elements as we want
$example[] = 13;

var_dump($example);
// Sample output: array(1, 2, 3, 5, 8)

Arrays in PHP are actually implemented using an Ordered Hash Map so we can put any value in any position using anything as key or let PHP manage the keys. An example of an array with keys that resembles a Java HashMap:

<?php
$example = [];
$example['a'] = 20;
$example['b'] = 50;

var_dump($example);
// Sample output: array('a' => 20, 'b' => 50)

With all this flexibility it is easy to understand why PHP developer love arrays so much. However there are several cases where arrays leave a lot to be desired and as I have seen many cases of misuse I decided to describe some of the common problems I encounter. Let’s look at some examples.

The method that returns different:

<?php
function something() {
  if (someCondition()) {
    return ['result' => 10, 'name' => 'John'];
  }

  return ['failure' => 'Something went bad'];
}

$result = something();
if (isset($result['failure'])) {
    // Manage error case
}

In the code above the return of the something() function is different depending on an condition inside the function. The programmer who invokes this function needs to know what the possible results are and explicitly test for them.

The method that returns sometimes:

<?php
function something() {
  if (someCondition()) {
    return ['success' => true, 'result' => 10, 'name' => 'John'];
  }

  return ['success' => false, 'error' => 'Something went bad'];
}

$result = something();
if (!$result['success']) {
  // Handle error
}

In this second example the something() function always returns a parameter indicating the success or failure of the function, but we still have one more little problem: What the hell does the function return?

Nowadays it is extremely common for programmers to use an IDE to assist assist in development. One of the very useful features of the IDE is auto-complete text and indicate when the programmer makes a mistake. Unfortunately due to this dynamic nature of arrays the IDE is unable to deduce a function’s return, forcing the programmer to read the function’s code every time he/she needs to remember its return.

Add to this problem the fact that many functions invoke other functions, making the result very difficult to deduce because we are forced to read the code of all the functions to understand what is going on.

These problems above can easily be solved if we return objects from some specific from some specific class, especially when we define the return type. Let’s look at the first rewritten example:

<?php
class ProcessingResult {
  private $success = false;
  private $result = 0;
  private $name = '';
  private $error = '';

  public function isSuccess() {
    return $this->success;
  }

  public function setSuccess($success) {
    $this->success = $success;
  }

  public function getResult() {
    return $this->result;
  }

  public function setResult($result) {
    $this->result = $result;
  }

  public function getName() {
    return $this->name;
  }

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

  public function setError($error) {
    $this->error = $error;
  }

  public function getError() {
    return $this->error;
  }
}

function something(): ProcessingResult {
  $result = new ProcessingResult();

  if (someCondition()) {
    $result->setSuccess(true);
    $result->setResult(10);
    $result->setName('John');

    return $result;
  }

  $result->setSuccess(false);
  $result->setError('Something went wrong');

  return $result;
}


$result = something();

if ($result->isSuccess()) {
  // Handle error
}

The code above may seem long, but it makes it much clearer to other programmers what your real intent is and it makes it very clear what values are available when you return. As a bonus the IDEs can now deduce the return type, as well as providing much better auto-completion.