Monate Media Part two: Domain Architecture →
Open source · PHP 8.5 · Free forever

Advanced PHP,
properly understood

Thirty lessons that take you from “I know what an interface is” to designing service graphs a container can wire itself — with the tests to prove they behave. SOLID, dependency injection, reflection, containers, TDD and object lifecycle.

Local, CLI-first and version-locked to PHP 8.5. Every lesson ships runnable examples, a code challenge and a closed-book quiz, and a check.php harness walks the challenges in order and stops at the first one still unsolved.

30lessons across six modules
28code challenges, each with a reference solution
28closed-book quizzes with answer keys
125runnable examples

The six modules

Strictly sequential. Each assumes the one before it — Module 4 cannot be understood without Module 3, and Module 5 exists to prove why Module 3 mattered.

01

OOP Building Blocks

All five SOLID principles, then the choice that defines everything after it: composition over inheritance.

Static asymmetric visibility · clone with · traits
02

Advanced Types & Enums

Use the type system as an enforcement mechanism, not documentation. Liskov, variance, hooks and enums.

#[\Override] · #[\NoDiscard] · property hooks
03

Dependency Injection & IoC

Why new inside a constructor is the root of untestable code, and the three ways to fix it.

Constructor promotion · interface type hints
04

Container Automation

Build a service container from scratch with Reflection, then replace it with PHP-DI and ship a real API.

Reflection API · PHP-DI 7 · Slim 4
05

Automated Testing & TDD

Why DI is the prerequisite for testing at all — then PHPUnit, doubles, red-green-refactor, and what not to assert.

PHPUnit 11 · SQLite integration tests
06

Object Lifecycle & State

PHP's share-nothing model, and what breaks the moment you move to a long-running worker.

Container scopes · immutable value objects

Six golden rules

Every design decision in the course runs through this list. They are not independent — composition enables DI, DI enables testability, testability sustains good design.

Module 5.0 is the one that surprises people: “Why Testing Requires DI”. Legacy code often cannot be tested because it is tightly coupled, not because testing is hard — which reframes a great deal of what looks like a testing problem as a design problem.

Then there is a part two

This course is about how to wire components. The sequel is about what the components should be — moving from loggers and mailers to a job card that knows the rules for cancelling itself, and a bill that refuses to be issued twice.

Finish this one first, properly. The sequel assumes you can compose objects, inject dependencies, wire a container and write a test with a fake — every one of those is used there without explanation.