Tutorial Laravel #25: Laravel Service Container dan Dependency Injection
1. Apa itu Service Container?
Service Container adalah IoC (Inversion of Control) container di Laravel - sebuah "kotak ajaib" yang tahu cara membuat object dan mengelola dependency antar class. Hampir semua fitur Laravel berjalan di atas service container.
Konsep dasarnya sederhana: daripada class membuat dependency-nya sendiri, dependency disuntikkan dari luar.
2. Dependency Injection (DI)
// Tanpa DI - buruk karena sulit ditest dan tightly coupled
class ArtikelController extends Controller
{
public function index()
{
$service = new ArtikelService(new ArtikelRepository(new DB()));
return $service->getAll();
}
}
// Dengan DI - lebih baik, Laravel otomatis inject
class ArtikelController extends Controller
{
// Laravel otomatis resolve dan inject ArtikelService
public function __construct(private ArtikelService $service) {}
public function index()
{
return $this->service->getAll();
}
}
3. Binding ke Container
<?php
// app/Providers/AppServiceProvider.php
namespace AppProviders;
use IlluminateSupportServiceProvider;
class AppServiceProvider extends ServiceProvider
{
public function register(): void
{
// Bind interface ke implementasi konkret
$this->app->bind(
AppContractsArtikelRepositoryInterface::class,
AppRepositoriesEloquentArtikelRepository::class
);
// Singleton - hanya dibuat satu kali, instance yang sama dipakai terus
$this->app->singleton(
AppServicesCacheService::class,
fn($app) => new AppServicesCacheService(config('cache.ttl'))
);
}
}
4. Membuat Service Class
<?php
// app/Services/ArtikelService.php
namespace AppServices;
use AppModelsArtikel;
use IlluminatePaginationLengthAwarePaginator;
class ArtikelService
{
public function getPublished(int $perPage = 10): LengthAwarePaginator
{
return Artikel::with(['user', 'kategori', 'tags'])
->where('status', 'published')
->latest()
->paginate($perPage);
}
public function create(array $data, int $userId): Artikel
{
return Artikel::create(array_merge($data, ['user_id' => $userId]));
}
public function update(Artikel $artikel, array $data): bool
{
return $artikel->update($data);
}
}
<?php
// Controller - inject service via constructor
namespace AppHttpControllers;
use AppServicesArtikelService;
class ArtikelController extends Controller
{
public function __construct(private ArtikelService $artikelService) {}
public function index()
{
$artikels = $this->artikelService->getPublished(12);
return view('artikel.index', compact('artikels'));
}
}
5. Service Provider
php artisan make:provider PaymentServiceProvider
<?php
// app/Providers/PaymentServiceProvider.php
namespace AppProviders;
use IlluminateSupportServiceProvider;
use AppServicesPaymentGateway;
use AppServicesMidtransGateway;
class PaymentServiceProvider extends ServiceProvider
{
public function register(): void
{
$this->app->singleton(PaymentGateway::class, function () {
return new MidtransGateway(
config('payment.midtrans.server_key'),
config('payment.midtrans.is_production')
);
});
}
}
6. Facades
Facade adalah cara mengakses service dari container dengan sintaks statis yang nyaman:
// Pakai facade
Cache::put('key', 'value', 3600);
$val = Cache::get('key');
Storage::put('file.txt', 'konten');
Log::info('Something happened');
// Di balik layar facade memanggil method dari object yang di-resolve container
7. Ringkasan
- Service Container mengelola pembuatan object dan dependency antar class
- Dependency Injection membuat kode lebih modular, mudah ditest, dan tidak tightly coupled
- Bind interface ke implementasi di
AppServiceProvider - Service class memisahkan business logic dari controller
Tutorial berikutnya membahas event, listener, dan observer di Laravel.
.jpg)
