DEV Community

Cover image for PHP: Stop Passing Arrays Everywhere

PHP: Stop Passing Arrays Everywhere

Lars Moelleken on January 25, 2026

Designing Explicit Data Contracts #blogPostAsWebApp: https://voku.github.io/PHPArrayBox/ Rule of thumb: If your array-shape PHPDoc ne...
Collapse
 
xwero profile image
david duymelinck

Let PHPStan enforce contracts

I let PHP enforce contracts. The problem I have with PHPStan to enforce contracts is that bugs can still occur when running the code in production.
I don't want to let PHPStan be the Typescript of PHP.

Collapse
 
suckup_de profile image
Lars Moelleken
  • Runtime errors means errors for users
  • High phpstan level shape your architecture for good (+ in the end also good autocompletion in the IDE)
  • nobody stops you to force things with php and still use phpstan (+ often phpstan force you to use types and interfaces etc. from php)
  • in the end nothing but real thinking prevents logic bugs 😊
Collapse
 
xwero profile image
david duymelinck

To be clear, I'm not against PHPStan.
It is the array<string, scalar> and non-empty-string comments that gives me the creeps.
In the end PHPStan is an additional tool. It shouldn't be considered as part of the language.

Thread Thread
 
suckup_de profile image
Lars Moelleken

Why not, even the language developers from php itself though of this more than once, same as hack (Facebook) who has introduced Generics since many years this way. docs.hhvm.com/hack/reified-generic...

Thread Thread
 
xwero profile image
david duymelinck

I think you misunderstood the last sentence of my comment.
It is not that I don't want generics in PHP, I don't want generics to handled only by PHPStan.

Thread Thread
 
suckup_de profile image
Lars Moelleken

I understand, that's why I used that example..., what if the php foundation would include it into php, same as hack did it? (Hack supports generics for type safety, but by default they are erased at runtime (type erasure).)

Thread Thread
 
xwero profile image
david duymelinck • Edited

Generics would be nice, but there are other ways to get the same result. For example an object that only accepts objects that have string and scalar properties.
It is more verbose than generics, but it has the same reliability.

Thread Thread
 
suckup_de profile image
Lars Moelleken

Yes, for many use-cases adding more code is often a more readable way instead of using generics but often enough at some important core points a generic is very helpful to maintaining reliability and to increase developer experience, see : phpstan.org/blog/generics-by-examples

Thread Thread
 
xwero profile image
david duymelinck • Edited

Sure there are cases where generics have added reliability over the current PHP functionality, like matching the input type with the output type.
At the moment the only thing we can do to be sure of that is by adding tests. But we are doing that anyway, so that is another way to mitigate the lack of generics.

I think the question is more what are the benefits of adding generics at this point?
Wouldn't it be easier to implement the generics functionality that is not covered by the current code practices as standalone features?
While I don't like PHPStan for generics, I seem to be an outsider voice. For example the new Symfony configuration threw the builder pattern overboard in favor of an array and one of the reasons they gave is IDE and PHPStan understanding of array shapes.
I don't think they would implemented it that way if they sensed there was no community support for it.

I understand generics are a well known concept, and it could make the transition from another programming language easier. But not every language with generics has the same functionality so then the PHP maintainers have to deal with people that are not satisfied with the way they added generics.

Thread Thread
 
suckup_de profile image
Lars Moelleken • Edited

As you already mentioned, phpstan (Generics and Co.) are only additional functions; PHP enforces reality. Static analysis enforces possibilities.

Two different ways to avoid "simple" errors, why shouldn't we use both?

PS: I am also like...

  • the DX (Developer Experience) part of it, like the instant feedback loop in the IDE (without running any test): if you pass 64 but only int<1,32> is allowed
  • the security aspect if your sql string is blocked because it contains non literal-string
  • the documentation part, so that we now can use syntax to describe what a yield will return Generator<int,User> and as extra we receive autocompletion in the IDE

... So why not?

Thread Thread
 
xwero profile image
david duymelinck

Sure if you want to use both that is fine. And your reasons are valid.
It is only using PHPStan when in can be in code that rubs me the wrong way.

And in the case of the Symfony configuration, I'm on board with their reasoning.
I can adjust my point of view on a case to case basis.

I think we have a similar perspective, it was the quote in my first comment that made me think we were further apart in opinions.

Collapse
 
spo0q profile image
spO0q • Edited

Solid post!

Indeed, these collections of mixed types are convenient but prone to various bugs.

PHPStan allows catching errors early, but it can be hard to use for legacy code. This is not uncommon teams set a lower level of constraint for old code that will be refactored later.

It becomes even more tedious with frameworks and helpers from third-party tools.

Collapse
 
suckup_de profile image
Lars Moelleken

You can generate a phpstan baseline file, where you ignore all old errros, and just start to write maintainable code.

For frameworks and other tools there are many phpstan extensions that supports you e.g. auto detect types directory from your sql queries or other magic stuff, if you really need it.