The Open Closed Principle becomes practical when PHP applications use strategies to add behavior without editing stable workflows.
The cost of changing stable code
A workflow becomes risky when every new business case requires editing the same class. Adding a new payment provider, discount type, export format, or notification channel should not force changes to a fragile central method. The Open Closed Principle asks us to design stable code that can accept new behavior through extension.
Conditionals are signals
A conditional is not automatically bad, but a conditional that grows with every feature is a design signal. If a calculate method checks ten payment types, each branch probably represents a separate behavior. Moving each branch into a strategy gives every behavior a home and lets the main workflow depend on a common interface.
A simple strategy shape
A DiscountStrategy interface might define apply(Order $order): Money. PercentageDiscount, FixedAmountDiscount, and LoyaltyDiscount implement the same method. The checkout service receives the correct strategy from a resolver. Adding a new discount means adding a new class and registering it. The checkout service does not need to change.
Resolvers and registries
Strategies often need a resolver. The resolver maps a key, type, or configuration value to the correct implementation. In Laravel, the service container can build the strategies, while a small registry stores the available keys. This keeps construction separate from usage and makes unsupported cases explicit.
Testing open closed designs
Testing becomes easier because the stable workflow can be tested with fake strategies, and each strategy can be tested independently. This creates fast, focused tests. A failing test points to the behavior that changed rather than a large method that mixes many cases.
Avoid premature abstraction
Do not introduce strategies for every if statement. Use them when variation is real, when new cases are likely, or when the branch logic is large enough to deserve a name. The principle should reduce friction, not add ceremony. A small conditional can be clearer than a directory full of tiny classes.
The bigger picture
Strategy is one of the most practical ways to apply the Open Closed Principle in PHP. It also pairs well with dependency injection, composition, and clean architecture boundaries.
Internal reading path
This article is part of a connected OOP and design patterns series. Continue with these related guides:
- Strategy Pattern in PHP: Replacing Conditionals With Behavior
- SOLID Principles in PHP: A Practical Guide for Real Projects
- Composition Over Inheritance in Modern PHP
Practical checklist
- Name the responsibility before choosing a pattern.
- Prefer small contracts where behavior varies or external services are involved.
- Keep controllers at the edge and move workflows into named application code.
- Add tests around the behavior that is most likely to change.
- Use patterns to reduce coupling, not to make simple code look advanced.