You Think You Know PHP (Outdated)
You can write PHP every day and still be surprised by how it compares, increments, and passes things around. Written for PHP 7, now outdated.
Outdated: I wrote this article in 2021 for PHP 7 and I don't maintain it anymore. Some of the behavior described here has changed in newer PHP versions, so check the official docs before relying on it.
PHP (recursive acronym for PHP: Hypertext Preprocessor) is a widely used open source general purpose scripting language that is especially suited for web development and can be embedded into HTML.
php.net
Many developers around the world started their careers with PHP, and a lot of them still do. According to W3Techs, PHP still runs about three quarters of the websites whose server side language is known. It's popular because you don't need a lot of experience to write working software with it, and because big platforms like WordPress, Joomla, and Drupal are built on it.
If you already work with PHP, you know what I'm talking about. And I think you think you know PHP. I'm sure you know a lot and you are a good developer, but some topics are less known than others.
Increment a string
Almost every developer has incremented a number at least once. You have a variable with a numeric value, and you increment or decrement it. Example:
<code class="language-php"><?php
$counter = 0; // Variable initialization
$counter++; // Post increment
$counter--; // Post decrement
++$counter; // Pre increment
--$counter; // Pre decrement
</code>All of these add 1 when incrementing and subtract 1 when decrementing.
But what if the value is a string, like "iPhone 1"? What happens then?
<code class="language-php"><?php
$modelName = 'iPhone 1';
$modelName++;
echo $modelName; // Prints: "iPhone 2"
</code>Note that decrement has no effect on strings, it only works on numbers. And increment doesn't touch spaces. So what happens if you keep incrementing, let's say ten times? Does it count up forever? No. In our example, it goes from "iPhone 1" to "iPhone 9", then wraps to "iPhone 0", and repeats. That's because of the space before the number. If you want it to go up to 99, the value must look like iPhone 01, and then it loops from 00 to 99.
And what if we remove the space, like "iPhone9"? Then it increments from right to left. When the 9 wraps to 0, it carries over and increments the "e" to "f", and you get "iPhonf0".
<code class="language-php"><?php
$modelName = "iPhone9";
echo ++$modelName; // Prints: "iPhonf0"
echo ++$modelName; // Prints: "iPhonf1"
</code>Since PHP 8.3, incrementing strings that contain non alphanumeric characters (like the space in "iPhone 1") and decrementing non numeric strings are deprecated. If you really need this behavior, use the new str_increment() function.
For more information about increment in PHP, see the docs.
in_array is not what you think
The name says it checks if an item is in an array, and that's true, but you have to be careful how you use it. in_array can compare in two ways: strict and non strict. The name doesn't make that clear, so many people use it without the strict flag, and that can lead to unexpected results.
Example:
<code class="language-php">$array = ['first element', 'second element'];
var_dump(in_array(0, $array));
</code>In PHP 7, this prints true. In PHP 8 it prints false, because PHP 8 changed how numbers are compared with non numeric strings.
Another example:
<code class="language-php">$array = ['1 apple', '2 oranges'];
var_dump(in_array(1, $array));
var_dump(in_array(2, $array));
</code>Guess what?! In PHP 7, both print true. In PHP 8, both print false.
And this one is still surprising, even in PHP 8:
<code class="language-php">$array = ['any thing', '0 oranges'];
var_dump(in_array(true, $array)); // true
</code>It prints true, because any non empty string is considered equal to true.
Why does this happen? PHP has two kinds of comparison. The strict one uses three equal signs ===, and the loose one uses two ==. The strict comparison first checks that both values have the same type, and only then compares them. The loose comparison converts the values to a common type first, for example a non empty string to true when you compare it with a boolean. The rules for these conversions changed between versions, which makes it even harder to predict.
So always use strict mode: in_array($needle, $array, true). For more information, see the in_array docs.
ArrayAccess makes your object look like an array, but array functions won't work
I think this is a weird design. If your object implements the ArrayAccess interface, you can access its values as if it were an array. But you can't use array functions like in_array on it. Instead you get a TypeError saying the function expects an array but got an object.
You couldn't throw exceptions from __toString()
Before PHP 7.4, it was impossible to throw an exception from __toString. If you did, you got a fatal error. Since PHP 7.4 it's allowed.
Objects are passed by reference? No
I hear this a lot: "objects are passed by reference". Probably because when you pass an object to a function that changes it, the original object changes too. The result looks the same, but PHP objects are not passed by reference.
A PHP reference is an alias, allowing two different variables to write to the same value.
In PHP, a variable that holds an object doesn't contain the object itself. It contains an identifier of the object, and PHP uses that identifier to find the actual object. So when you pass the object to a function or assign it to another variable, you copy the identifier, and both copies point to the same object.
A simple example:
<code class="language-php">class Type {}
$x = new Type();
$y = $x;
$y = "New value";
var_dump($x); // Prints the object
var_dump($y); // Prints "New value"
$z = &$x; // $z is a reference to $x
$z = "New value";
var_dump($x); // Prints "New value"
var_dump($z); // Prints "New value"
</code>Final words
PHP is an old language and it has evolved a lot. As a result, it has many features. Some of them are popular, and some are not. If you know another lesser known PHP feature, contact me on X @salem_hsn.

If this was useful
Telc German B1 Exam Success Kit (20/80 Rule)
The 20% of German that keeps showing up in the telc B1 exam. Learn it first and walk in already knowing what to expect. €25