Several years ago, when the PHP-FIG (PHP Framework Interop Group) created its first PSRs (PHP Standard Recommendations) they started some big changes in the PHP ecosystem. The standard for class auto-loading was created to go hand-in-hand with the then new package manager Composer. PSRs for coding standards were defined, which I’m sure helped a lot of teams to leave coding standard discussions behind. The old tabs versus spaces debate was forever settled and the jokes about it now feel quite outdated.
Next up were the PSRs that aimed for the big goal: framework interoperability. It started with an easy one: PSR-3 for logging, but it took quite some time before the bigger ones were tackled, e.g. request/response interfaces, HTTP client and server middleware interfaces, service container interfaces, and several others. The idea, if I remember correctly, was that frameworks could provide implementation packages for the proposed interfaces. So you could eventually use the Symfony router, the Zend container, a Laravel security component, and so on.
I remember there were some troubles though. Some PSRs were abandoned, some may not have been developed to their full potential, and some may have been over-developed. I think it’s really hard to find common ground between framework implementations for all these abstractions, and to define abstractions in such a way that users and implementers can both be happy (see for example an interesting discussion by Anthony Ferrara about the HTTP middleware proposal and an older discussion about caching).
One of the concerns I personally had about PSR abstractions is that once you have a good abstraction, you don’t need multiple implementation packages. So why even bother creating a separate abstraction for others to use? Why not just create a single package that has both the implementation and the abstraction? It turns out, that doesn’t work. Why? Because package maintainers sometimes just abandon a package. And if that happens, the abstraction becomes useless too because it is inside that abandoned package. So developers do like to have a separate abstraction package that isn’t even tied to their favorite vendor.
(By the way, I think it’s strange for frameworks to have their own Interfaces or Contracts package for their abstractions. I bet there are 0 cases where someone using Laravel or Symfony keeps using its abstractions, but not its implementations. Anyway… If you have a different experience, or want to share your story about these packages, please submit a comment below!)
Is it safe to depend on PSR abstraction packages?
Back in 2013, Igor Wiedler made a lasting impression with their article about dependency responsibility. By now we all know that by installing a vendor package you can import bugs and security issues into your project. Another common concern is the stability of the package: is it going to be maintained for a long time? Are the maintainers going to change it often?
Yes, these concerns should be addressed, and I think in general they are not considered well enough. But we need to distinguish between different kinds of packages. Packages have a certain level of stability which is in part related to its abstractness and the number of dependencies it has (if you’re interested in this topic, check out my book “Principles of Package Design”).
The abstractness of a package is based on the number of interfaces versus the number of classes. Since abstract things are supposed to change less often than concrete things, and in fewer ways, an abstract package will be a stable package and it will be more reliable than less abstract, i.e. concrete packages (I think this is why frameworks provide those Interface or Contract packages: as an indication of their intended stability).
Another reason for a package to become stable is when it is used by many people. This is more of a social principle: the maintainers won’t change the package in drastic ways if that makes the users of the package angry. Of course, we have semantic versioning and backward compatibility promises for th
Truncated by Planet PHP, read more at the original (another 10480 bytes)