© 2026 Laravel

Laravel Service Container là gì? Deep Dive để Master Dependency Injection

3 phút đọc 7 lượt xem
#laravel #service container #dependency injection #architecture

Nếu bạn từng viết Laravel như sau:

$userService = new UserService();

Thì bạn đang bypass một trong những thứ mạnh nhất của Laravel.

Service Container chính là thứ giúp Laravel trở nên “magic”.

Và cũng là thứ phân biệt:

Developer bình thường vs Senior Laravel Engineer

#Service Container là gì?

Service Container là một công cụ quản lý dependency.

Hiểu đơn giản:

Nó giúp bạn tạo object mà không cần tự new.

Thay vì:

$service = new UserService(new UserRepository());

Laravel sẽ tự resolve:

public function __construct(UserService $service)

Không cần new, không cần wiring.

#Dependency Injection (DI) trong Laravel

Laravel sử dụng DI thông qua constructor:

class UserController
{
    public function __construct(UserService $service)
    {
        $this->service = $service;
    }
}

Container sẽ:

  • Tạo UserService
  • Inject vào controller

#Container hoạt động như thế nào?

Flow:

Controller cần UserService
Container kiểm tra binding
Nếu có → resolve
Nếu không → auto resolve (reflection)
Inject dependency

Laravel dùng Reflection để tự động resolve class.

#Binding trong Service Container

#Bind cơ bản

app()->bind(UserRepositoryInterface::class, UserRepository::class);

Mỗi lần resolve → tạo instance mới

#Singleton

app()->singleton(UserService::class, function () {
    return new UserService();
});

Chỉ tạo 1 lần duy nhất

#Bind instance

app()->instance('config.custom', $config);

#Service Provider – nơi bind container

public function register()
{
    $this->app->bind(
        UserRepositoryInterface::class,
        UserRepository::class
    );
}

Rule quan trọng:

  • register() → bind
  • boot() → không bind

#Auto Resolution (Laravel cực mạnh)

Laravel có thể tự resolve nếu:

  • Class không có dependency phức tạp
  • Hoặc dependency cũng resolve được
public function index(UserService $service)

Không cần bind vẫn chạy

#Real Case Production

  • Swap implementation
app()->bind(PaymentInterface::class, StripePayment::class);

Sau này:

app()->bind(PaymentInterface::class, PaypalPayment::class);

Không cần sửa business logic

  • Testing
app()->bind(UserService::class, FakeUserService::class);

Mock dễ dàng

  • Multi environment
if (app()->environment('local')) {
    app()->bind(CacheService::class, FakeCache::class);
} else {
    app()->bind(CacheService::class, RedisCache::class);
}

#Anti-pattern (rất nhiều dev mắc phải)

Lạm dụng container

app(UserService::class)->doSomething();

Sai vì:

  • Hidden dependency
  • Khó test

✅ Đúng:

public function __construct(UserService $service)

Over abstraction

  • Interface cho mọi thứ
  • Không cần thiết vẫn abstraction

Dẫn đến:

  • Code phức tạp
  • Khó maintain

Logic trong Service Provider

public function boot()
{
    // xử lý logic business
}

Sai hoàn toàn

#Performance & Optimization

  • Singleton giúp giảm memory
  • Avoid resolve nhiều lần
  • Cache container (production)
php artisan config:cache
php artisan route:cache

#Mindset

Junior:

DI để code đẹp hơn

Senior:

DI để giảm coupling, tăng testability và scale system

#Khi nào nên dùng Service Container?

#Nên dùng

  • Service layer
  • Repository
  • External integration

#Không cần dùng

  • Class đơn giản
  • Logic nhỏ

#Kết luận

Service Container là:

Nền tảng kiến trúc của Laravel

Hiểu nó giúp bạn:

  • Viết code clean
  • Dễ test
  • Dễ scale