post-image

[Bài đọc] Repository Pattern

2. Cơ bản về Laravel Framework

Repository Pattern

Repository Pattern là một mẫu kiến trúc cho phép chúng ta tách biệt các tầng khác nhau của ứng dụng, giúp cho mã nguồn trở nên trong sáng và dễ duy trì và mở rộng hơn. Các tầng trong repository pattern bao gồm:

  • Tầng controller: Xử lý request và response của HTTP
  • Tầng service: Xử lý các logic nghiệp vụ
  • Tầng repository: Xử lý các thao tác truy xuất CSDL

Các tầng của Repository Pattern

Lợi ích của việc sử dụng repository pattern:

  • Mã nguồn gọn gàng, minh bạch
  • Dễ truy xuất mã nguồn, dễ duy trì
  • Dễ thay đổi (vì khi thay đổi ở một tầng thì không ảnh hưởng đến các tầng còn lại)
  • Dễ mở rộng (thông qua cơ chế kế thừa)
  • Dễ triển khai kiểm thử tự động (vì có thể kiểm thử lần lượt cho từng tầng)

Triển khai repository pattern trong Laravel

Để triển khai repository pattern, chúng ta lần lượt thực hiện các thao tác sau:

  1. Xây dựng tầng repository
  2. Xây dựng tầng service. Sử dụng cơ chế dependency injection để tiêm repository vào trong service.
  3. Xây dựng tầng controller. Sử dụng cơ chế dependency injection để tiêm service vào trong controller.

Xây dựng tầng Repository

Khai báo interface RepositoryInterface chứa các phương thức thông dụng của tất cả các repository:

<?php

namespace App\Repositories;

interface RepositoryInterface
{
    public function all();

    public function create(array $data);

    public function update(array $data, $id);

    public function delete($id);

    public function show($id);
}

Khai báo lớp Repository implement các phương thức của RepositoryInterface:

<?php

namespace App\Repositories;

use Illuminate\Database\Eloquent\Model;

class Repository implements RepositoryInterface
{

    //Implementation

}

Khai báo interface của Repository tương ứng với model đang được phát triển, chẳng hạn khai báo UserRepository để khai báo các phương thức đặc trưng của model User, chẳng hạn như phương thức findByEmail(), posts(), comments()…

<?php

namespace App\Repositories;

use Illuminate\Database\Eloquent\Model;

interface UserRepository
{

    //Specific action of users

}

Khai báo Repository tương ứng với model đang được phát triển, kế thừa từ interface vừa khai báo trước đó, chẳng hạn, khai báo lớp UserRepositoryImpl để thực hiện các thao tác với CSDL liên quan đến model User. 

<?php

namespace App\Repositories;

use Illuminate\Database\Eloquent\Model;

class UserRepositoryImpl extends Repository implements UserRepository
{

    //Implementation

}

Trong lớp UserRepositoryImpl chúng ta viết các mã để truy xuất đến CSDL của model User, chẳng hạn như tìm kiếm theo email, lấy danh sách bài viết, lấy danh sách phản hồi…

Như vậy, lớp UserRepositoryImpl sẽ được kế thừa các phương thức của lớp Repository và đồng thời tự triển khai các phương thức của interface UserRepository.

Khai báo trong AppServiceProvider để chuẩn bị phục vụ cho Dependency Injection:

<?php

namespace App\Providers;

use Illuminate\Support\ServiceProvider;

class AppServiceProvider extends ServiceProvider
{
    /**
     * Bootstrap any application services.
     *
     * @return void
     */
     public function boot()
     {

    }

    /**
     * Register any application services.
     *
     * @return void
     */
     public function register()
     {
         $this->app->singleton(
                 \App\Repositories\UserRepository::class,
                 \App\Repositories\UserRepositoryImpl::class
             );
     }
}

Trong đoạn mã trên, chúng ta khai báo rằng: Nếu có một đối tượng của interface UserRepository được yêu cầu thì Laravel sẽ tạo ra một đối tượng của lớp UserRepositoryImpl để cung cấp cho nó thông qua cơ chế Dependency Injection.

Như vậy, chúng ta đã có thể tiêm UserRepository vào trong UserService. Chúng ta cũng làm tương tự đối với tầng service.

Xây dựng tầng service

Khai báo interface ServiceInterface chứa các phương thức thông dụng của tất cả các service:

<?php

namespace App\Services;

interface ServiceInterface
{
    public function all();

    public function create(array $data);

    public function update(array $data, $id);

    public function delete($id);

    public function show($id);
}

Khai báo lớp Service implement các phương thức của ServiceInterface:

<?php

namespace App\Services;

class Service implements ServiceInterface

{

    //Implementation

}

Khai báo interface của Service tương ứng với model đang được phát triển, chẳng hạn khai báo UserService để khai báo các phương thức đặc trưng của model User, chẳng hạn như phương thức findByEmail(), posts(), comments()…

<?php

namespace App\Services;

interface UserService

{

    //Specific action of users

}

Khai báo service tương ứng với model đang được phát triển, kế thừa từ interface vừa khai báo trước đó, chẳng hạn, khai báo lớp UserServiceImpl để thực hiện các logic nghiệp vụ liên quan đến user.

<?php

namespace App\Services;

use App\Services\UserRepository;

class UserServiceImpl extends Service implements UserService
{

    public $userRepository;

    public function __construct(UserRepository $userRepository) {

        $this->userRepository = $userRepository;

    }

    // MoreImplementation

}

Như chúng ta thấy, đối tượng UserRepository đã được tiêm vào trong UserServiceImpl thông qua cơ chế dependency injection trong constructor.

Trong lớp UserUserImpl chúng ta viết các mã để xử lý các thao tác nghiệp vụ liên quan đến user, chẳng hạn như tìm kiếm theo email, lấy danh sách bài viết, lấy danh sách phản hồi…

Như vậy, lớp UserServiceImpl sẽ được kế thừa các phương thức của lớp Service và đồng thời tự triển khai các phương thức của interface UserService.

Khai báo trong AppServiceProvider để chuẩn bị phục vụ cho Dependency Injection:

<?php



...

        $this->app->singleton(
                \App\Services\UserService::class,
                \App\Services\UserServiceImpl::class
            );
...

Trong đoạn mã trên, chúng ta khai báo rằng: Nếu có một đối tượng của interface UserService được yêu cầu thì Laravel sẽ tạo ra một đối tượng của lớp UserServiceImpl để cung cấp cho nó thông qua cơ chế Dependency Injection.

Khai báo tầng controller

Khai báo lớp Controller để xử lý các request và response của HTTP. Lớp controller này sẽ sử dụng service tương ứng thông qua cơ chế dependency injetion.

<?php

namespace App\Http\Controllers;

class UserController extends BaseController
{

    public $userService;

    

    public function __construct(UserService $userService){

        $this->userService = $userService;

    }

    
    public function create(Request $request)
    {

        ...

        $this->userService->create($user);

        ...

    }

}

Như vậy, chúng ta đã hoàn thành các bước để phát triển một tính năng dựa theo kiến trúc repository. Các tính năng khác cũng sẽ được phát triển theo luồng tương tự.

Leave a Reply

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