Remix.run Logo
▲ hparadiz a day ago

With how good PHPDoc and Phan are these days I don't really think about it anymore. You can sort of have typed array by implementing Iterator, Countable, ArrayAccess, and optionally Indexing but I assume you mean defining types of array values.

▲Tadpole9181 a day ago | parent | next [-]

If I could take a tangent and talk about the infuriating implicit-casting behavior of arrays in PHP?

  declare(strict_types=1);
  
  /\* @var array<string, int> \*/
  function foo(string $key) {
      echo $key;
  }
  
  $foo = [
      'a' => 10,
      '1' => 15,
  ];
  
  foreach ($foo as $key => $_) {
      foo($key);
  }
The static analyzer will say this is safe (sans a bleeding edge setting in PHPStan), but it will throw a type error when it runs. Because the string '1' is, despite having strict types enabled, still implicitly cast to the number 1.
▲tredre3 20 hours ago | parent | next [-]

Internally PHP has three distinct array types (the distinction is mainly for optimization purposes, it doesn't enforce anything): Regular arrays (continuous numeric keys), sparse arrays (all keys are integers but there can be holes) and hashmaps (anything goes).

I wish that the implicit casting you describe only happened in the two first case. In your example PHP already knows that $foo is a hashmap, so I'd want it to keep '1' as is!

Unfortunately for all of us, for every person surprised by this behavior, there's someone who relies on it. So it'll never change.

Best we can hope is to have better array types eventually (no, the SPL isn't it).

▲wesammikhail a day ago | parent | prev [-]

I had this happen to me yesterday in spite of knowing about it because I was rushing. I added phone numbers as array keys to deduplicate the whole set. Some ended up as ints and some as strings.

PHP arrays are the most versatile part of the language. They're what actually makes the language so good in so many ways.

But typed arrays are a freaking requirement at this point and I've been screaming about it for years now... alas no response.

▲hparadiz 20 hours ago | parent [-]

It's a performance optimization in this case. '1' is a string and you can hash it like all the other strings with PHP's fork of djbx33a or you can immediately store it at memory index 1. PHP tends to have a lot of old code using numeric strings so the performance benefit of not hashing all of those is obvious.

▲wesammikhail 18 hours ago | parent [-]

I never dug into it but I suspected memory optimization to be the reason. Thanks for confirming.

▲someothherguyy a day ago | parent | prev [-]

pretty naive take, no run time guarantees, basically swinging on hope to keep your shit together. phpstan drops types on static analysis for deeply nested arrays/objects for example. or even those with many members.