service container in laravel with example

he Laravel service container, also known as the Inversion of Control (IoC) container, is a powerful tool for managing class dependencies and performing dependency injection.  It acts as a central registry for your application's classes, allowing Laravel to automatically resolve and inject required dependencies when needed.   

 

 

 

 

 

 

 

 

 

 

 Key Concepts: 

 

 

 

 

 

 

 

 

 

 Binding:   

 Registering a class or an interface and its implementation with the container.  This tells the container how to build an instance of that class or what implementation to use for a given interface. 

 

 

 

 

 

 

 

 

 Resolving:   

 Retrieving an instance of a registered class or implementation from the container.  The container handles the creation of the object and its dependencies. 

 

 

 

 

 

 

 

 

 Dependency Injection:   

 The process of providing a class with its dependencies through its constructor or setter methods, rather than the class creating them itself.  The service container automates this. 

 

 

 

 

 

 

 

 

 

 Example: 

 

 

 

 

 Consider a scenario where you have a  NotificationService  responsible for sending notifications and a  UserService  that utilizes this service. 

 

 

 

 

 

 

 

 

 

 Code 

 

 

 

 

 

 

 

 

 

 

 

 // app/Services/NotificationService.php

namespace App\Services;

class NotificationService

{

 public function send(string $message): string

 {

 return "Sending Notification: " . $message;

 }

}

// app/Services/UserService.php

namespace App\Services;

class UserService

{

 protected NotificationService $notificationService;

 // The NotificationService is injected via the constructor

 public function __construct(NotificationService $notificationService)

 {

 $this->notificationService = $notificationService;

 }

 public function notifyUser(string $message): string

 {

 return $this->notificationService->send($message);

 }

} 

 

 

 Using the Service Container: 

 

 

 

 

 

 Automatic Resolution in Controllers/Jobs:   Laravel automatically resolves dependencies for constructors in controllers, jobs, and other framework-managed classes. 

 

 

 

 

 

 

 

 

 

 

 Code 

 

 

 

 

 

 

 

 

 

 

 

 // app/Http/Controllers/UserController.php

 namespace App\Http\Controllers;

 use App\Services\UserService;

 use Illuminate\Http\Request;

 class UserController extends Controller

 {

 public function __construct(protected UserService $userService)

 {

 // The UserService instance is automatically injected here

 }

 public function showNotifications()

 {

 $message = $this->userService->notifyUser('Welcome to our application!');

 return view('notifications', compact('message'));

 }

 } 

 

 

 

 Manual Resolution:   You can also explicitly resolve instances from the container using the  app()  helper or  App::make() . 

 

 

 

 

 

 

 

 

 

 

 Code 

 

 

 

 

 

 

 

 

 

 

 

 use App\Services\UserService;

 // ...

 $userService = app()->make(UserService::class);

 $message = $userService->notifyUser('Manual notification!'); 

 

 

 Binding Interfaces to Implementations (Advanced): 

 

 

 

 

 This is particularly useful for testability and flexibility. 

 

 

 

 

 

 

 

 

 

 Code 

 

 

 

 

 

 

 

 

 

 

 

 // app/Contracts/MailerInterface.php

namespace App\Contracts;

interface MailerInterface

{

 public function sendMail(string $to, string $subject, string $body): string;

}

// app/Services/SmtpMailer.php

namespace App\Services;

use App\Contracts\MailerInterface;

class SmtpMailer implements MailerInterface

{

 public function sendMail(string $to, string $subject, string $body): string

 {

 return "Sending SMTP mail to {$to}: {$subject} - {$body}";

 }

}

// app/Providers/AppServiceProvider.php (or a custom Service Provider)

namespace App\Providers;

use App\Contracts\MailerInterface;

use App\Services\SmtpMailer;

use Illuminate\Support\ServiceProvider;

class AppServiceProvider extends ServiceProvider

{

 public function register(): void

 {

 $this->app->bind(MailerInterface::class, SmtpMailer::class);

 }

} 

 

 

 Now, anywhere you type-hint  MailerInterface , the container will inject an instance of  SmtpMailer . 

 

 

 

 

 

 

 

 

 

 Code 

 

 

 

 

 

 

 

 

 

 

 

 // In a controller or job

use App\Contracts\MailerInterface;

class OrderController extends Controller

{

 public function __construct(protected MailerInterface $mailer)

 {

 // $this->mailer is an instance of SmtpMailer

 }

 public function processOrder()

 {

 $this->mailer->sendMail('user@example.com', 'Order Confirmation', 'Your order has been placed.');

 }

}