Repository Pattern di PHP, Pendekatan arsitektur semakin populer

Seputar PHP815 Views

Repository Pattern menjadi salah satu pendekatan arsitektur yang semakin populer di kalangan developer PHP modern. Pola ini dianggap mampu menghadirkan struktur kode yang lebih rapi, terukur, dan mudah dikembangkan. Banyak programmer menyebutnya sebagai jembatan antara domain logic dan data layer karena karakteristiknya yang memisahkan logika bisnis dari cara data diambil maupun disimpan.

Dalam dunia PHP yang kini semakin bergerak ke arah arsitektur bersih dan scalable, Repository Pattern menempati posisi yang penting. Pola ini sering digunakan dalam framework besar seperti Laravel dan Symfony, atau bahkan aplikasi PHP native yang ingin memiliki struktur profesional.

Mengapa Repository Pattern Meningkat Populer

Repository Pattern memberikan cara kerja yang lebih terorganisir. Banyak aplikasi modern membutuhkan fleksibilitas yang tinggi, terutama saat skala sistem mulai membesar. Dengan Repository Pattern, setiap akses data ditempatkan dalam satu lapisan khusus sehingga program menjadi lebih mudah diuji dan dikembangkan.

“Saat pertama kali memindahkan query mentah ke repository, saya merasa seolah beban besar di kode saya hilang begitu saja. Baru sadar bahwa arsitektur itu bukan soal keren atau rumit tetapi soal kenyamanan jangka panjang.”


Konsep Dasar Repository Pattern

Konsep ini pada dasarnya sangat sederhana. Repository bertugas menjadi perantara antara aplikasi dan sumber data. Sumber data bisa berupa database, API eksternal, file sistem, atau kombinasi semuanya.

Secara umum repository memiliki tanggung jawab berikut.

Memisahkan Logika Bisnis dari Akses Data

Sebelum repository digunakan, banyak developer menulis query SQL langsung di controller atau service. Pola ini membuat kode sulit dikelola dan rawan duplikasi. Repository mengabstraksi seluruh kebutuhan akses data sehingga controller hanya fokus pada logika bisnis.

Menyediakan Antarmuka Seragam

Repository memberi standar terhadap cara aplikasi mengambil data. Developer tidak perlu memikirkan apakah data berasal dari MySQL, MongoDB, atau API lain. Semua diakses melalui fungsi seragam seperti getAll, findById, atau create.

Mempermudah Pengujian Unit

Dengan repository, kita bisa membuat mock data sehingga proses pengujian tidak selalu bergantung pada database asli.


Struktur Repository Pattern di PHP

Sebelum masuk ke contoh kode, ada baiknya memahami struktur umum repository.

  • Interface Repository : Bagian ini berfungsi sebagai kontrak. Interface mendefinisikan apa saja metode yang harus dimiliki sebuah repository.
  • Implementasi Repository : Bagian ini menjadi tempat seluruh logika database ditulis, seperti query SQL atau ORM.
  • Entity atau Model : Repository biasanya bekerja dengan entity atau model. Entity ini mewakili data yang digunakan aplikasi.
  • Service atau Controller : Bagian ini menjadi pengguna dari repository. Service akan memanggil repository tanpa mengetahui detail cara repository mengambil data.

Contoh Struktur Folder Repository PHP

Struktur sederhana yang sering digunakan adalah seperti berikut.

app/
  Models/
    User.php
  Repositories/
    UserRepositoryInterface.php
    UserRepository.php
  Services/
    UserService.php

Struktur ini tentu bisa berkembang sesuai kebutuhan proyek.


Contoh Penerapan Repository Pattern Versi Native PHP

Berikut contoh repository sederhana menggunakan PHP tanpa framework.

Membuat Interface Repository

<?php
interface UserRepositoryInterface {
    public function getAll();
    public function findById($id);
    public function create($data);
}

Interface di atas mendefinisikan tiga fungsi penting yang harus dimiliki UserRepository.

Membuat Implementasi Repository

<?php
class UserRepository implements UserRepositoryInterface {

    private $connection;

    public function __construct(PDO $connection) {
        $this->connection = $connection;
    }

    public function getAll() {
        $stmt = $this->connection->query("SELECT * FROM users");
        return $stmt->fetchAll(PDO::FETCH_ASSOC);
    }

    public function findById($id) {
        $stmt = $this->connection->prepare("SELECT * FROM users WHERE id = ?");
        $stmt->execute([$id]);
        return $stmt->fetch(PDO::FETCH_ASSOC);
    }

    public function create($data) {
        $stmt = $this->connection->prepare("INSERT INTO users (name, email) VALUES (?, ?)");
        $stmt->execute([$data['name'], $data['email']]);
        return $this->connection->lastInsertId();
    }
}

Repository di atas sudah berisi implementasi query database dengan PDO.

Menggunakan Repository di Service

<?php
class UserService {

    private $repository;

    public function __construct(UserRepositoryInterface $repository) {
        $this->repository = $repository;
    }

    public function listUsers() {
        return $this->repository->getAll();
    }

    public function registerUser($name, $email) {
        return $this->repository->create([
            'name' => $name,
            'email' => $email
        ]);
    }
}

Service hanya fokus pada logika bisnis tanpa mempedulikan bagaimana data disimpan.


Penggunaan Repository Pattern dalam Framework Laravel

Laravel merupakan framework yang sangat ramah terhadap penerapan repository. Meskipun Laravel menggunakan Eloquent ORM, repository tetap dapat memberikan layer abstraksi tambahan.

Contoh interface sederhana.

<?php
namespace App\Repositories;

interface PostRepositoryInterface {
    public function all();
    public function find($id);
}

Implementasi repository menggunakan Eloquent.

<?php
namespace App\Repositories;

use App\Models\Post;

class PostRepository implements PostRepositoryInterface {

    public function all() {
        return Post::all();
    }

    public function find($id) {
        return Post::find($id);
    }
}

Controller menggunakan repository melalui dependency injection.

<?php
class PostController extends Controller {

    private $repository;

    public function __construct(PostRepositoryInterface $repository) {
        $this->repository = $repository;
    }

    public function index() {
        return response()->json($this->repository->all());
    }
}

Keuntungan Menerapkan Repository Pattern di PHP

Repository Pattern memberikan banyak manfaat dalam proyek jangka panjang. Pola ini mengurangi duplikasi kode dan membuat struktur aplikasi lebih jelas. Developer lebih mudah menemukan bagian tertentu karena repository menjadi pusat akses data.

“Repository Pattern mengajari saya bahwa coding itu bukan sekadar mengeksekusi logika, tetapi juga mengatur logika agar tetap rapih ketika aplikasi berkembang.”

  • Mempermudah Perpindahan Teknologi Database : Jika suatu hari aplikasi harus pindah dari MySQL ke MongoDB atau PostgreSQL, perubahan hanya terjadi pada layer repository saja.
  • Mempercepat Pengembangan Tim : Repository membuat standar pada cara mengambil data sehingga developer baru lebih cepat memahami struktur.
  • Mengurangi Kode Berulang : Dengan repository, fungsi akses data dapat digunakan kembali oleh banyak bagian aplikasi.

Repository Pattern untuk API Eksternal

Repository tidak hanya untuk database tetapi juga API. Contoh repository berikut menggunakan Curl untuk mengambil data dari API.

<?php
class WeatherRepository {

    public function getWeather($city) {
        $url = "https://api.example.com/weather?city=" . urlencode($city);
        $response = file_get_contents($url);
        return json_decode($response, true);
    }
}

Repository ini menyederhanakan akses API sehingga service hanya memanggil satu fungsi saja.

Menggabungkan Repository dengan Dependency Injection Container

Framework modern menyediakan fitur dependency injection. Repository bisa dihubungkan otomatis ke interface melalui binding.

Contoh binding sederhana di Laravel.

$this->app->bind(
    App\Repositories\UserRepositoryInterface::class,
    App\Repositories\UserRepository::class
);

Dengan binding seperti ini, controller otomatis menerima implementasi repository tanpa konfigurasi manual.

Repository Pattern dalam Aplikasi Berskala Besar

Dalam proyek enterprise, repository biasanya digunakan bersama service layer, DTO, dan domain model. Tujuannya adalah menciptakan arsitektur yang stabil dan mudah diuji.

Pada sistem besar, satu entity bisa memiliki beberapa repository khusus, seperti repository untuk proses pencarian cepat, repository untuk update batch, dan repository untuk integrasi API khusus.

Menambah Fungsi Filter dan Pagination dalam Repository

Repository bisa diperluas sesuai kebutuhan. Berikut contoh fungsi filter sederhana.

public function filterByName($name) {
    $stmt = $this->connection->prepare("SELECT * FROM users WHERE name LIKE ?");
    $stmt->execute(["%$name%"]);
    return $stmt->fetchAll(PDO::FETCH_ASSOC);
}

Pagination juga bisa ditambah.

public function paginate($limit, $offset) {
    $stmt = $this->connection->prepare("SELECT * FROM users LIMIT ? OFFSET ?");
    $stmt->execute([$limit, $offset]);
    return $stmt->fetchAll(PDO::FETCH_ASSOC);
}

Penyusunan Repository yang Lebih Kompleks

Beberapa aplikasi memerlukan repository dengan logika data yang lebih rumit. Misalnya integrasi beberapa sumber data sekaligus.

Contoh repository gabungan.

<?php
class HybridUserRepository implements UserRepositoryInterface {

    private $mysqlRepo;
    private $apiRepo;

    public function __construct($mysqlRepo, $apiRepo) {
        $this->mysqlRepo = $mysqlRepo;
        $this->apiRepo = $apiRepo;
    }

    public function getAll() {
        $local = $this->mysqlRepo->getAll();
        $remote = $this->apiRepo->fetchRemoteUsers();
        return array_merge($local, $remote);
    }

    public function findById($id) {
        return $this->mysqlRepo->findById($id);
    }

    public function create($data) {
        return $this->mysqlRepo->create($data);
    }
}

Repository ini menggabungkan data lokal dan API eksternal.

Repository Pattern untuk Unit Testing

Repository sangat membantu dalam unit testing karena kamu bisa membuat mock repository.

Mock sederhana.

class MockUserRepository implements UserRepositoryInterface {
    public function getAll() { return [['id' => 1, 'name' => 'Test']]; }
    public function findById($id) { return ['id' => $id, 'name' => 'Mock']; }
    public function create($data) { return 99; }
}

Dengan mock seperti ini, service dapat diuji tanpa harus terhubung ke database asli.

Leave a Reply

Your email address will not be published. Required fields are marked *