Understand the Laravel Container Concept with Real Life Example
The term “Container” is one of the mostly used term in the Laravel framework. But it’s not always clear to everyone what it is and how it works. In this post, I will try to explain the container concept with a real life example.
The Coffee Shop Analogy
Imagine you’re in a coffee shop, a place where you can order a variety of coffee drinks. The coffee shop acts as a service container. When you order a coffee, say a cappuccino, you don’t need to know how to make it yourself; you just tell the barista what you want, and they prepare it for you using the coffee shop’s resources (coffee beans, milk, espresso machines, etc.).
In this analogy:
- Coffee Shop (Service Container): This is where all the resources (services) are available. It knows how to prepare any coffee drink (service) you order.
- Barista (Service Resolver): Acts as the mechanism within the coffee shop that understands your order and knows how to fulfill it by using the resources available in the shop.
- Coffee Drinks (Services): These are the various services the coffee shop offers, like a cappuccino, latte, or espresso. Each drink requires a specific process and resources to make.
Applying the Analogy to Software Development
Translating this back to software development:
- Service Container: This is a powerful tool in a framework (like Laravel) that manages the creation and distribution of services (objects). It knows how to instantiate and configure objects based on your requests.
- Services: These are the classes and objects that perform specific tasks in your application, such as sending emails, logging messages, or handling database interactions.
- Resolving Services: When you request a specific service from the container, it’s like ordering a coffee. You don’t need to know how the service is constructed or configured; the container handles it for you and provides the ready-to-use service.
Why Use a Service Container?
- Simplification: Just as you don’t need to know how to make every type of coffee drink, you don’t need to manually manage the creation and configuration of objects in your application.
- Flexibility: You can easily change how a service is made without altering the code that uses it, similar to how the coffee shop can change its recipe or ingredients without affecting how you order a drink.
- Efficiency: The container can manage shared resources, like a single database connection that many parts of your application use, similar to how a coffee shop uses one espresso machine to make various drinks.
Enough theory. Let’s write some code now.
Write container in PHP project
Define Coffee Types (Services)
First, let’s define a few classes that represent different types of coffee drinks. These classes will have a method to describe how to serve the drink.
interface Coffee {
public function serve();
}
class Espresso implements Coffee {
public function serve() {
return "Serving an Espresso.\n";
}
}
class Cappuccino implements Coffee {
public function serve() {
return "Serving a Cappuccino with frothy milk.\n";
}
}
class Latte implements Coffee {
public function serve() {
return "Serving a Latte with steamed milk.\n";
}
}
Implement the CoffeeShop (Service Container)
Now, we’ll create the CoffeeShop
class, which acts as our service container. It will have the ability to register coffee types and serve them.
class CoffeeShop {
protected $recipes = [];
// Register a coffee type
public function register($coffeeName, Callable $make) {
$this->recipes[$coffeeName] = $make;
}
// Serve a coffee based on the registered recipe
public function serve($coffeeName) {
if (!isset($this->recipes[$coffeeName])) {
return "Sorry, we don't serve $coffeeName.\n";
}
$coffee = call_user_func($this->recipes[$coffeeName]);
return $coffee->serve();
}
}
Register Coffee Types and Serve Them
Finally, we’ll register each coffee type with the coffee shop and then ask it to serve various drinks.
// Create the coffee shop (service container)
$coffeeShop = new CoffeeShop();
// Register coffee types (services)
$coffeeShop->register('espresso', function() { return new Espresso(); });
$coffeeShop->register('cappuccino', function() { return new Cappuccino(); });
$coffeeShop->register('latte', function() { return new Latte(); });
// Serve the coffee
echo $coffeeShop->serve('espresso');
echo $coffeeShop->serve('cappuccino');
echo $coffeeShop->serve('latte');
echo $coffeeShop->serve('mocha'); // This should return an error message
Output
Serving an Espresso.
Serving a Cappuccino with frothy milk.
Serving a Latte with steamed milk.
Sorry, we don't serve mocha.
Conclusion
In essence, a service container in software development abstracts the complexities of creating and managing service objects, allowing developers to focus on the higher-level functionality of their application. Just as a coffee shop efficiently provides you with a variety of drinks without requiring you to know the details of how each is made, a service container simplifies the management of service objects and their dependencies in your application.
If you are a visual learner, you can take a look on this video: