Loops with each

Loops are among the most frequently used constructs in PHP. There are multiple ways of writing a loop. The preferred one seems to be foreach, because it is convenient and safe. Another, less convenient and more error-prone way of iterating would be each:

$list = [1, 2, 3];

while ($item = each($list)) {

The result is:

array(4) {
  [1] => int(1)
  'value' => int(1)
  [0] => int(0)
  'key' => int(0)

array(4) {
  [1] => int(2)
  'value' => int(2)
  [0] => int(1)
  'key' => int(1)

array(4) {
  [1] => int(3)
  'value' => int(3)
  [0] => int(2)
  'key' => int(2)

As you can see, each returns a data structure on each iteration. In addition, you need to manually reset the internal pointer by calling reset() to be able to iterate multiple times. You really should be using foreach instead, which is also a lot faster than each.

Using each has thus been deprecated in PHP 7.2 and will probably be removed from PHP in version 8. So since PHP 7.2, the first iteration of an each loop will create the following warning:

Deprecated: The each() function is deprecated.
This message will be suppressed on further calls in ...

Curly Brace Syntax

Curly brace syntax for accessing array elements has been deprecated:

$array = [1, 2, 3];


Executing the code shown above will print the output shown below:

PHP Deprecated: Array and string offset access syntax
with curly braces is deprecated in ...

Simply use $array[1] instead of $array{1} to get rid of the deprecation warning.

Using array_key_exists() on Objects

Since version 4, PHP has evolved from a procedural language into a full-blown object-oriented language. Thus, PHP has historically treated objects and arrays interchangeably in some ways. What is the difference, after all, between iterating over array elements and iterating over object attributes? In a loosely typed PHP without non-public visibility of object attributes, there is in fact no big difference.

I a type-safe PHP with public, protected, and private attribute visibility on objects, an object is quite different from an array. In due course, PHP becomes more and more strict about not treating an object like an array.

Before PHP 7.4, you could use array_key_exists() to check for the existence of an object attribute:

class Foo
    private int $bar;

$foo = new Foo;
var_dump(array_key_exists('bar', $foo));
var_dump(array_key_exists('baz', $foo));

Unsurprisingly, this will output:


In PHP 7.4, using array_key_exists() on objects has been deprecated. The deprecation error message even suggests alternatives:

PHP Deprecated:
array_key_exists(): Using array_key_exists() on objects is deprecated.
Use isset() or property_exists() instead in ...

OOP purists might argue that being able a private attribute is an implementation detail, and thus even attempting to check for existence already breaks encapsulation. We would agree, by the way. Just because something is possible, this does not mean that you should be doing it.

Deprecate wrong parameter order for implode()

Turning an array into a string is a common output operation. You might, for example, want to turn an array of values into a comma-separated list:

var_dump(implode(', ', [1, 2, 3]));

The result is:

string(7) "1, 2, 3"

The correct parameter order when calling implode() is the glue string first, then the array to implode. For historic reasons, PHP has also allowed to pass the array first, then the glue string:

var_dump(implode([1, 2, 3], ', '));

Due to the different parameter types, PHP can always tell which is which. Nevertheless, passing both parameters in the wrong order has now been deprecated:

PHP Deprecated: implode():
Passing glue string after array is deprecated.
Swap the parameters in ...
string(7) "1, 2, 3"

One of the reasons for such a change is that static code analysis have a hard time dealing with type information like “it can be a string, or an array, and by the way, both are correct”.

Luckily, the fix is very easy, and the deprecation message already told you. Just swap the two parameters and live happily ever after.