Kiến thúc cơ bản về Repository trong Laravel

2nd Nov 2022
Kiến thúc cơ bản về Repository trong Laravel
Table of contents

Design Patterns là gì ?

Design Pattern (mẫu thiết kế) là giải pháp chung để giải quyết các vấn đề phổ biến  khi thiết kế phần mềm trong lập trình hướng đối tượng OOP. Ví dụ:

Khi gặp vấn đề, mỗi developer sẽ có những phương án khác nhau để giải quyết. Tuy
nhiên các phương án đó chưa thực sự tối ưu. Do đó, Design Pattern sinh ra để giải
quyết vấn đề này, khiến các vấn đề có tính chất tương tự được giải quyết trong một
khuôn mẫu nhất định. Các khuôn mẫu này đã được chuẩn tối ưu nhất.

Việc sử dụng Design Pattern sẽ giúp chúng ta tiết kiệm thời gian và công sức để tìm cách giải quyết cho những vấn đề đã có phương án tối ưu. Tuy nhiên nó khá trừu tượng với những coder mới tìm hiểu.

>> Tìm hiểu về Repository Pattern và những cách sử dụng nó hiệu quả trong lập trình

>> Laravel: Thử tập tành ProductRepository trong Repository Pattern

Các framework hiện nay như Laravel, Codeigniter, Spring.. đều có sử dụng những Design Patterns có sẵn.

Repository Pattern Trong Laravel

Repository Pattern là một mẫu thiết kế trong Design Pattern. Repository là lớp trung gian nằm giữa BLL (Business Logic Layer) và DAL (Data Access Layer). Mục đích của Repository là để giúp cho việc truy cập dữ liệu chặt chẽ và bảo mật hơn.

Repository là phần trung gian giữa dữ liệu và logic

Hiểu một cách đơn giản, Repository sẽ nằm giữa lớp Model và Controller. Thay vì viết code xử lí trong Controller thì ta sẽ viết trong  Repository rồi gọi trong constructor của Controller.

Việc sử dụng Repository trong một dự án sẽ khiến Code dễ đọc hơn, hạn chế các lỗi trong việc truy vấn và lặp code.

Ví dụ: Trong phần lớn các ứng dụng Laravel, chúng ta sẽ gặp mã như sau trong Controller.

class UsersController extends Controller
{
   public function index()
   {
       $users = User::all();

       return view('users.index', [
           'users' => $users
       ]);
   }
}

Trông thì có vẻ không có vấn đề gì. Tuy nhiên nếu khách hàng đề xuất thay đổi các cấu trúc dữ liệu và thay vì trong MySQL hay PostgresSQL thì bây giờ chúng ta sẽ lưu dữ liệu ở một nơi khác, trong một công cụ mà không có Eloquent hỗ trợ thì việc viết như vậy sẽ dẫn đến tình trạng rất khó để thay đổi tất cả các Controller. Mọi việc triển khai phải dựa trên các interface . Trong trường hợp có sự thay đổi, bạn không cần thay đổi toàn bộ project mà chỉ cần tạo một interface. Ví dụ:

class UsersController extends Controller
{
   private $userRepository;

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

   public function index()
   {
       $users = $this->userRepository->all();

       return view('users.index', [
           'users' => $users
       ]);
   }
}

Với cách viết như thế này, khi phải thay đổi cấu trúc dữ liệu thì chúng ta sẽ tạo một lớp implement  UserRepositoryInterface và chứa các logic cho phép lấy data theo một cách mới.  

Cách xây dựng Repository trong Laravel

1. Tạo base Repository

Tạo thư mục Repository trong app như sau:
-- app
---- Repository
------ Eloquent
-------- UserRepository.php
-------- BaseRepository.php
------ UserRepositoryInterface.php
------ EloquentRepositoryInterface.php

Hiểu nôm na, BaseRepository và EloquentRepositoryInterface là các lớp cha chứa các methods được sử dụng phổ biến trong mọi repository. Trong đó, BaseRepository implements RepositoryInterface là nơi triển khai các phương thức như CRUD, còn RepositoryInterface là nơi khai báo các phương thức đó.

EloquentRepository

namespace App\Repository;


use Illuminate\Database\Eloquent\Model;

/
* Interface EloquentRepositoryInterface
* @package App\Repositories
*/
interface EloquentRepositoryInterface
{
   /
    * @param array $attributes
    * @return Model
    */
   public function create(array $attributes): Model;

   /**
    * @param $id
    * @return Model
    */
   public function find($id): ?Model;
}
...

BaseRepository.php

<?php

namespace App\Repository\Eloquent;

use App\Repository\EloquentRepositoryInterface; 
use Illuminate\Database\Eloquent\Model;

class BaseRepository implements EloquentRepositoryInterface 
{
    /
     * @var Model
     */
     protected $model;

    /
     * BaseRepository constructor.
     *
     * @param Model $model
     */
    public function __construct(Model $model)
    {
        $this->model = $model;
    }
 
    /
    * @param array $attributes
    *
    * @return Model
    */
    public function create(array $attributes): Model
    {
        return $this->model->create($attributes);
    }
 
    /
    * @param $id
    * @return Model
    */
    public function find($id): ?Model
    {
        return $this->model->find($id);
    }
    ...
}

2. Khai báo  Service Provider

php artisan make:provider RepositoryServiceProvider

Khai báo trong hàm register()

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

Tiếp theo là khai báo Provider mà chúng ta vừa tạo ở config/app.php. Thêm vào 'providers' :

App\Providers\RepositoryServiceProvider::class

3. Viết Interface và Repository tương ứng với Model.

UserRepositoryInterface.php

<?php
namespace App\Repository;

use App\Model\User;
use Illuminate\Support\Collection;

interface UserRepositoryInterface
{
    // Lấy tất cả users
   public function all(): Collection;
}

UserRepository.php

<?php

namespace App\Repository\Eloquent;

use App\Model\User;
use App\Repository\UserRepositoryInterface;
use Illuminate\Support\Collection;

class UserRepository extends BaseRepository implements UserRepositoryInterface
{

   /
    * Hàm constructor.
    *
    * @param User $model
    */
   public function construct(User $model)
   {
       // Khai báo model User
       parent::construct($model);
   }

   /
    * @return Collection
    */
   public function all(): Collection
   {
       // Lấy hết các users
       return $this->model->all();
   }
}

4. Viết Controller

UserController.php

class UsersController extends Controller
{
   private $userRepository;
  
   public function __construct(UserRepositoryInterface $userRepository)
   {
       $this->userRepository = $userRepository;
   }

   public function index()
   {
       $users = $this->userRepository->all();

       return view('users.index', [
           'users' => $users
       ]);
   }
}

Tổng kết

Như vậy, chúng ta đã tìm hiểu cơ bản về Repository và thực hành. Trong trường hợp không muốn triển khai Eloquent, chúng ta thay đổi App\Repository\Eloquent\UserRepository.php ví dụ App\Repository\Mongo\UserRepository.php. Mọi thứ vẫn sẽ hoạt động bình thường ngay cả khi chúng ta thay đổi về phía dữ liệu.

Bạn thấy bài viết này như thế nào?
0 reactions

Add new comment

Image CAPTCHA
Enter the characters shown in the image.

Related Articles

Danh sách này có 4 sản phẩm nên chưa cần phân trang, nếu số lượng sản phẩm lên đến vài chục sản phẩm

Hiện nay kiến trúc Microservices đang là chủ đề được cộng đồng Developer vô cùng quan tâm

Hôm nay chúng ta cùng tìm hiểu về Eloquent trong Laravel với mối quan hệ nhiều - nhiều (many to many relationship)

Kiểm soát hợp lí truy cập nội dung trang web là yếu tố quyết định trong việc điều hành một máy chủ bảo mật.

Trong lập trình web, authorization (phân quyền) là chức năng vô cùng quan trọng và không thể thiếu