# PHP packages that stand alone and still work together

> Modular PHP libraries that work without being tied to a framework; they became the 39-package InitPHP ecosystem and Framework3.

- What it does today: A family of 39 PHP packages — Router, Database, Cache, Mailer, Socket and the rest — each usable standalone or together, all shipped through Composer/Packagist under MIT. Any PHP developer who wants the pieces without buying into a framework can install them today.
- Form: Open source
- State: Became a product
- Focus: Developer tooling & CI
- Started: 2021-01-01
- Left Labs: 2022-08-12
- Technologies: PHP, Composer, PHPUnit
- Tags: #php, #library, #open-source
- Source code: https://github.com/InitPHP
- Website: https://initphp.org
- This one became a product: InitPHP (https://www.muhammetsafak.com.tr/en/portfolio/initphp/)
- Source: https://www.muhammetsafak.com.tr/en/labs/initphp-lab/
- Language: en-US
- Author: Muhammet Şafak

---
A PHP package is either part of a framework or a tool that stands on its own.
Once you want both at the same time, writing a shared core package is the first
solution that comes to mind — and it is also the wrong one.

## On its own, or as a family

What was tried: let parts like Router, Database, Cache, Mailer and Socket work
meaningfully when installed alone, and still form a framework when combined
with the other packages in the family. The parts were written separately and
each one answered a question by itself.

## Thirty-nine packages and the framework on top

Thirty-nine independent packages plus a minimalist MVC framework sitting on top
of them (Framework3). The common ground is type safety and PHPUnit tests;
distribution goes through Composer/Packagist under the MIT licence.

## PSR instead of a shared core

"Both alone and together" collides at exactly one point: if packages have to
know about each other, there is a dependency between them, and that dependency
breaks standalone installation.

The first solution that came to mind was a shared core package — something like
`initphp/core` carrying the interfaces and common helpers. That road would have
brought two things at once: every package would gain one more dependency, and
since no library outside the family would know that core, the family would
close in on itself.

The ground chosen was the PHP-FIG standards. Logger implements PSR-3, Container
implements PSR-11; packages know a shared interface contract rather than each
other. What that buys: the InitPHP Container accepts the InitPHP Logger, but it
also accepts Monolog, and the InitPHP Logger plugs into somebody else's PSR-11
container. What resolved the contradiction was not a core of the family's own
but a contract that already existed outside it.

## Thirty-nine packages instead of one library

The family's second decision was about packaging. One `initphp/initphp` package
instead of thirty-nine repositories, thirty-nine release lines and thirty-nine
Packagist entries would have made maintenance markedly cheaper.

The cost would have been passed on to the user. A project that wants only a Router
would have to install the Socket server, the Mailer and the Queue as well; every
upgrade would carry the changes of ten packages it never uses. What the split
buys: `composer require initphp/router` brings only the Router, and you never
see the TCP/TLS/UDP/SSL surface of the Socket library.

So what keeps it maintainable is not shared code but shared discipline: the same
level of type safety in every package, the same PHPUnit habit, the same PSR
compliance. The family holds together because it was written to the same rules,
not because it shares a dependency.

## The road to the ecosystem

The collection stopped being a set of scattered packages and became a maintained
open source ecosystem. Details in the portfolio.
