Commerce Platforms 3 min read Jul 29, 2026

How does Laravel handle dependency injection?

How Laravel Handles Dependency InjectionLaravel simplifies Dependency Injection (DI) by using its Service Container. DI is a design pattern where a class's dependencies are provided externa...

Post

How Laravel Handles Dependency Injection


Laravel simplifies Dependency Injection (DI) by using its Service Container. DI is a design pattern where a class's dependencies are provided externally rather than the class creating them itself. Laravel automatically resolves dependencies for classes and methods using the container, ensuring that your code is clean, modular, and testable.


How It Works

  1. Automatic Resolution: Laravel can resolve dependencies automatically if the class is type-hinted in the constructor or method.
  2. Service Container: Laravel's Service Container binds and resolves dependencies. If a dependency isn't bound explicitly, Laravel tries to resolve it automatically by looking at the class type-hint.
  3. Type-Hinting: You can type-hint classes, interfaces, or objects in constructors or methods, and Laravel will resolve them.


Dependency Injection in Laravel

1. Constructor Injection

Laravel automatically resolves dependencies passed into the constructor.

Example:
  namespace App\Services;
  
  class PaymentGateway {
      public function charge($amount) {
          echo "Charging $amount.";
      }
  }
  namespace App\Http\Controllers;
  
  use App\Services\PaymentGateway;
  
  class OrderController {
      protected $paymentGateway;
  
      public function __construct(PaymentGateway $paymentGateway) {
          $this->paymentGateway = $paymentGateway;
      }
  
      public function processOrder() {
          $this->paymentGateway->charge(100);
      }
  }
  • When you call the processOrder method, Laravel will:
  1. Detect the PaymentGateway type-hint.
  2. Automatically resolve and inject the PaymentGateway instance.


2. Method Injection

Laravel allows dependency injection directly into controller methods.

Example:
  namespace App\Http\Controllers;
    
    use App\Services\PaymentGateway;
    
    class CheckoutController extends Controller {
        public function checkout(PaymentGateway $paymentGateway) {
            $paymentGateway->charge(200);
        }
    }
  • Here, Laravel injects the PaymentGateway dependency when the checkout method is called.

3. Interface Injection

You can bind an interface to a specific implementation in the Service Container.

Example:
  1. Define an Interface:
  namespace App\Contracts;
  
  interface PaymentGatewayInterface {
      public function charge($amount);
  }
  1. Create an Implementation:
  namespace App\Services;
  
  use App\Contracts\PaymentGatewayInterface;
  
    class StripePaymentGateway implements PaymentGatewayInterface {
        public function charge($amount) {
            echo "Charged $amount via Stripe.";
        }
    }
  1. Bind the Interface:
  namespace App\Providers;
  
  use Illuminate\Support\ServiceProvider;
  use App\Contracts\PaymentGatewayInterface;
  use App\Services\StripePaymentGateway;
  
  class AppServiceProvider extends ServiceProvider {
      public function register() {
          $this->app->bind(PaymentGatewayInterface::class, StripePaymentGateway::class);
      }
  }
  1. Use Interface in Controller:
  namespace App\Http\Controllers;
  
  use App\Contracts\PaymentGatewayInterface;
  
  class PaymentController extends Controller {
      protected $paymentGateway;
  
      public function __construct(PaymentGatewayInterface $paymentGateway) {
          $this->paymentGateway = $paymentGateway;
      }
  
      public function processPayment() {
          $this->paymentGateway->charge(300);
      }
  }
  • Laravel resolves the interface PaymentGatewayInterface and injects the StripePaymentGateway implementation.

4. Using Closures

You can bind dependencies using closures.

Example:
  app()->bind('customService', function () {
      return new \App\Services\CustomService();
  });
  
  $customService = app()->make('customService');


Real-World Use Case: E-Commerce Checkout

In an e-commerce application:

  1. Use an interface (PaymentGatewayInterface) to define the payment gateway contract.
  2. Bind different implementations (e.g., StripePaymentGateway, PayPalPaymentGateway).
  3. Inject the interface into controllers or services, allowing flexible and testable code.


Benefits of Dependency Injection in Laravel

  1. Decoupling: Reduces dependency on specific implementations, making the code easier to maintain and test.
  2. Reusability: Allows reuse of services across the application.
  3. Flexibility: Easily swap implementations for different environments (e.g., testing vs production).
  4. Testability: Facilitates unit testing by injecting mock dependencies.


Conclusion

Laravel's automatic resolution and Service Container make dependency injection seamless, promoting clean and modular application design.

Related reading