Day 32: Building PSR-11: Implementing a DI container from scratch.

Designing and Building a High-Scale PHP Content Management System ~10 min read 60 min hands-on

Day 32. Building PSR-11: Implementing a DI container from scratch.

Welcome back, fellow architects and engineers!

Today, we're diving deep into a concept that might seem foundational, but its strategic implementation is absolutely non-negotiable for systems aspiring to handle the kind of scale we're talking about: Dependency Injection (DI) and building a PSR-11 compliant container from scratch.

You might think, "Why build one when frameworks give it for free?" That's a fair question. But just like understanding how a CPU works helps you write better algorithms, understanding the mechanics of a DI container empowers you to wield it with surgical precision, especially when optimizing for 100 million requests per second. It's about transcending mere usage and achieving mastery.

The Elephant in the Room: The "Bootload Tax" and Persistent Runtimes

In our journey towards a high-scale PHP CMS, we've touched upon PHP's evolution. Traditional PHP-FPM, while robust, incurs a "bootload tax" on every single request. This means for each incoming request, your entire application environmentβ€”classes, configurations, and dependenciesβ€”is initialized from scratch. At 100M RPS, this becomes an astronomical performance bottleneck.

This is where the shift to persistent runtimes like Swoole or RoadRunner becomes critical. With persistent runtimes, your application boots once, and then processes requests continuously within that long-lived process. This fundamentally changes the game for how we manage resources and services.

Core Insight: A well-designed DI container is your strategic ally here. It allows you to define how and when services (like database connections, cache clients, or API clients) are instantiated. In a persistent runtime, this means you can instantiate expensive resources once at application boot and reuse them across thousands, even millions, of requests, effectively eliminating the "bootload tax" for these critical components. This isn't just about clean code; it's about raw, unadulterated throughput.

What is a DI Container, Really?

At its heart, a DI container is a registry that knows how to create and provide instances of your application's services (dependencies). Instead of your classes creating their dependencies directly, they declare what they need, and the container injects them. This is the "Inversion of Control" principle in action.

Why is this critical for high-scale?

  1. Decoupling: Services don't know how their dependencies are created, only what they need. This makes your system modular, easier to test, and incredibly flexible for swapping implementations (e.g., a mock cache for testing, a Redis cache for production). This agility is paramount when iterating quickly on a high-scale system.

  2. Lifecycle Management: As mentioned, it allows for controlled instantiation. You can define services as "singletons" (one instance shared across the entire application lifetime, perfect for persistent runtimes) or "prototypes" (a new instance every time, useful for request-specific objects). This fine-grained control over resource allocation is a cornerstone of efficient high-scale systems.

  3. Testability: Decoupled components are inherently easier to test in isolation. You can mock dependencies without rewriting core logic, leading to more robust and reliable code – a must-have when maintaining a system under immense load.

Our Goal: A PSR-11 Compliant Container

PSR-11 is a standard interface for DI containers. By implementing it, our container becomes interoperable with other PSR-11 compliant libraries and frameworks. This is a best practice for building maintainable PHP applications.

The ContainerInterface is simple:

  • get(string $id): Finds and returns an entry of the container by its identifier.

  • has(string $id): Returns true if the container can return an entry for the given identifier.

Component Architecture & Fit in the Overall System

Keep going with the full lesson

The rest of this lesson β€” plus its implementation guide, runnable scripts and source code β€” is included with the course or an All Access plan. Create a free account to start the free lessons in every course.

Already a member? Sign in