PHP is a dynamically typed language. In addition, it performs some automatic type conversion. Since PHP 7.0, it is possible to declare strict_types=1, which means that type hints are enforced. For me, this leads to unexpected behavior. Consider the following (condensed) example.

<?php declare(strict_types=1);

$key = "42";
$value = "What's the answer?";

$store = [$key => $value];
foreach ($store as $key => $value) {
  echo "Length of key '$key' is " . strlen($key) . PHP_EOL;

The above code will throw the TypeError strlen() expects parameter 1 to be string, int given. Without the declare statement, the script runs perfectly fine. So what’s the issue?

The error says that and integer was passed to strlen. We have passed the key of the array to the function. When creating the array, we set the key to "42".

The PHP manual on arrays says:

[…] Additionally the following key casts will occur:

  • Strings containing valid decimal integers, unless the number is preceded by a + sign, will be cast to the integer type. E.g. the key “8” will actually be stored under 8. On the other hand “08” will not be cast, as it isn’t a valid decimal integer.
  • […]

This means, our string key "42" was automatically converted to the integer 42. In this contrived example, it’s easy to fix, but I can imagine countless examples where user input is used as array keys, which then, in turn, might lead to type errors. A prime example is $_GET.