The Power of Laravel’s Service Container: A Practical Guide
Learn how to leverage the Service Container to manage class dependencies in your Larevel application easily.
If you’ve been working with Laravel for a while, you may have heard of the Service Container. But what is it, and how can you use it to take your Laravel projects to the next level?
In this tutorial, we will thoroughly explore the Service Container tool and show you how to use it to manage class dependencies in your Laravel application. Let’s start with a simple example and gradually refactor it into a more advanced example to show you how to harness the full power of the Service Container.
Getting Started with a Simple Example
Let’s start by creating a new controller and injecting a specific class into it. We will use a payment gateway as an example of a typical scenario where you need to charge a customer’s credit card or bank account when they place an order on your website
- Create a controller by running the following command:
php artisan make:controller PayOrderController
2. Add a store()
method to the controller and include a PaymentGateway
dependency:
namespace App\Http\Controllers;
use App\Billing\PaymentGateway;
class PayOrderController extends Controller
{
public function store(PaymentGateway $paymentGateway)
{
// code to charge customer's account
}
}
3. Create a PaymentGateway
class inside the app/Billing
directory:
namespace App\Billing;
class PaymentGateway
{
public function charge($amount)
{
$bankResponse = [
'amount' => $amount,
'confirmation_number' => str_random(10),
];
return $bankResponse;
}
}
4. Now you can use the $paymentGateway
object inside the store()
method to charge the customer's account:
public function store(PaymentGateway $paymentGateway)
{
$amount = 2500; // $25.00
$bankResponse = $paymentGateway->charge($amount);
return view('receipt', [
'amount' => $bankResponse['amount'],
'confirmation_number' => $bankResponse['confirmation_number'],
]);
}
This is a simple example of how to use the Service Container tool in Laravel. However, as your project grows, you will find that managing class dependencies can become more complex. That’s when the Service Container really shines!
Advanced Application of the Service Container
Let’s take the above example and refactor it to utilize the Service Container more efficiently. We will use a ServiceProvider
to register our PhonePayPaymentGateWay
class, and add some additional functionality to demonstrate the flexibility of the Service Container.
- Create an
PaymentGatewayInterface
interface:
namespace App\Billing;
interface PaymentGatewayInterface
{
public function charge($amount);
}
2. Update the PhonePePaymentGateway
class to implement the interface:
namespace App\Billing;
class PhonePePaymentGateway implements PaymentGatewayInterface
{
public function charge($amount){
#phone pe payment gateway payment charge api implemtation
}
}
3. Create a PaymentGatewayServiceProvider
class inside the app/Providers
directory:
namespace App\Providers;
use Illuminate\Support\ServiceProvider;
use App\Billing\PaymentGatewayInterface;
use App\Billing\PaymentGateway;
class PaymentGatewayServiceProvider extends ServiceProvider
{
public function register()
{
$this->app->singleton(PaymentGatewayInterface::class, function ($app) {
return new PhonePePaymentGateway();
});
}
}
4. Add the PaymentGatewayServiceProvider
to the providers
array in your config/app.php
file:
'providers' => [
// ...
App\Providers\PaymentGatewayServiceProvider
]
This registers the PaymentGatewayServiceProvider
with Laravel, allowing it to use the Service Container to manage dependencies and inject instances of the PhonePePaymentGateway
to a class where it’s needed.
Once you have added the provider, you can now access the PhonePePaymentGateway
instance anywhere in your application by simply type-hinting it in the constructor of a class that needs it. For example:
namespace App\Http\Controllers;
use App\Services\PaymentGateway;
class PaymentController extends Controller
{
protected $paymentGateway;
public function __construct(PaymentGatewayInterface $paymentGateway)
{
$this->paymentGateway = $paymentGateway;
}
public function store()
{
// use the payment gateway to process the payment
$result = $this->paymentGateway->charge(2500);
// handle the payment result
}
}
In this example, we inject an instance of the PaymentGatewayInterface
into the PaymentController
constructor. This is possible because we have registered PaymentGatewayServiceProvider
with Laravel, which tells it how to create instances of the PhonePePayementGateway
class.
With this setup, we can easily swap the implementation of the PaymentGateway
class with a different one simply by updating the PaymentGatewayServiceProvider
.
Here is an example of how to proceed if we need to swap payment gateway:
namespace App\Providers;
use Illuminate\Support\ServiceProvider;
use App\Billing\PaymentGatewayInterface;
use App\Billing\PaymentGateway;
class PaymentGatewayServiceProvider extends ServiceProvider
{
public function register()
{
$this->app->singleton(PaymentGatewayInterface::class, function ($app) {
return new GooglePayPaymentGateway();
});
}
}
In this example, we are changing PaymentGatewayServiceProvider
with a GooglePayPaymentGateway
class.
And here is GooglePayPaymentGateway
class:
namespace App\Billing;
class GooglePayPaymentGateway implements PaymentGatewayInterface
{
public function charge($amount){
#googlepay payment gateway payment charge api implemtation
}
}
We can implement the rest of the functionality in our PaymentController
for charge will be the same as implement, and there is no need to change it.
This is the power of the Laravel Service Container and why it is such an important part of the framework!
Conclusion
Laravel’s Service Container is an essential and powerful tool for managing class dependencies in your application. By using the Service Container, you can easily define how your classes should be instantiated, and Laravel takes care of the rest. This not only simplifies your code but also makes it more modular and maintainable. I hope this article helped you get a good understanding of the Service Container’s basic principles and how to use them in your Laravel projects. As you continue working with Laravel, you will likely find more ways to take advantage of the Service Container and improve your application’s architecture.
Acknowledgments
I would like to thank the Laravel community and the Laravel documentation team for their invaluable contributions to the Laravel ecosystem.
Stay up to date with the latest trends in the development ecosystem by following Simform Engineering.