
What are Factories in PHP and how to use them
When working with object-oriented programming in PHP, sooner or later you’ll need to create objects in a more flexible, controlled, and scalable way. This is where Factories come in — a very useful design pattern that helps you encapsulate object creation logic.
What Is a Factory?
A Factory is a creational design pattern that provides a way to create objects without having to specify the exact class of the object being created. Instead of using new
directly everywhere, you centralize the object creation logic in a dedicated class or function.
This is useful when:
- You want to decouple your code from specific classes.
- The object creation logic is complex.
- You need to create different types of objects depending on certain parameters.
Basic Factory example
Let’s say we have a Vehicle
interface and two classes that implement it: Car
and Motorcycle
.
<?php interface Vehicle { public function move(): void; } class Car implements Vehicle { public function move(): void { echo "The car is moving"; } } class Motorcycle implements Vehicle { public function move(): void { echo "The motorcycle is moving"; } }
Now, we create a factory that takes care of creating the correct vehicle type based on a parameter:
<?php class VehicleFactory { public function createVehicle(string $type): Vehicle { if ( $type === 'car' ) { return new Car(); } if ( $type === 'motorcycle' ) { return new Motorcycle(); } throw new InvalidArgumentException("Invalid vehicle type: $type"); } }
Using the factory.
<?php $vehicleFactory = new VehicleFactory(); $myCar = $vehicleFactory->createVehicle('car'); $myCar->move(); // The car is moving 🚗 $myMoto = $vehicleFactory->createVehicle('motorcycle'); $myMoto->move(); // The motorcycle is moving 🏍️
Benefits of using a Factory
- Decoupling: The code that needs an object doesn’t have to know how it’s constructed.
- Reusability: If you need to change the creation logic, you do it in one place.
- Flexibility: You can return different subclasses or dynamically configured instances.
Static Factory
You can also implement the pattern using a static method:
<?php class VehicleFactory { public static function create(string $type): Vehicle { return match($type) { 'car' => new Car(), 'motorcycle' => new Motorcycle(), default => throw new InvalidArgumentException("Unsupported type: $type"), }; } } // Usage $vehicle = VehicleFactory::create('car'); $vehicle->move();
More realistic example: Factory with configuration
In more complex systems, object creation might depend on various parameters or even dependency injection. Let’s see an example:
<?php class DatabaseConnection { protected string $host; protected string $username; protected string $password; public function __construct(string $host, string $username, string $password) { $this->host = $host; $this->username = $username; $this->password = $password; } public function connect(): void { echo "Connecting to $this->host as $this->username\n"; } } class DatabaseFactory { public function createFromEnv(): DatabaseConnection { return new DatabaseConnection( getenv('DB_HOST'), getenv('DB_USER'), getenv('DB_PASS') ); } } // Usage $dbFactory = new DatabaseFactory(); $dbConnection = $dbFactory->createFromEnv(); $dbConnection->connect();
The Factory pattern is a powerful tool for creating objects in PHP in a controlled and flexible way. It’s especially helpful in medium to large applications where centralizing instantiation logic helps you keep your code clean, decoupled, and easier to maintain.