Repository Pattern là gì ? Sử dụng Repository Pattern trong Laravel

Chúng tôi rất vui mừng chia sẻ kiến thức sâu sắc về từ khóa Repository la gi để tối ưu hóa nội dung trang web và tiếp thị trực tuyến. Bài viết cung cấp phương pháp tìm kiếm, phân tích từ khóa và chiến lược hiệu quả. Cảm ơn sự quan tâm và hãy tiếp tục theo dõi để cập nhật kiến thức mới.

Trong nội dung bài viết này tất cả chúng ta sẽ cùng tìm hiểu về một vấn đề nói đến khá nhiều trong Laravel đó là Repository Pattern. Với những bạn mới tìm hiểu về Laravel chắc là cũng không nhiều để ý đến vấn đề này. Còn các bạn đi thực tập tại những đơn vị, các ban trainee thì chắc gặp sẽ được những trainer của mình nói tới từ khóa này. Vậy nó là gì mà, có thực sự cấp thiết không, tất cả chúng ta cùng tìm hiểu nhé.

Bạn Đang Xem: Repository Pattern là gì ? Sử dụng Repository Pattern trong Laravel

1. Khái niệm

Trước nhất để hiểu về khái niệm tất cả chúng ta sẽ cùng xem ảnh sau này 😃

Repository Pattern là một cách tổ chức source code trong Laravel. Nhìn vào ảnh này các ban có thể hình dung qua qua nó rồi chứ, Repository Pattern là lớp trung gian giữa tầng Data Access và Business Logic, hiểu môm na thì nó là lớp trung gian giữa việc truy cập tài liệu và xử lý logic. hỗ trợ cho việc truy cập tài liệu chặt chẽ và bảo mật thông tin hơn.

Thông thường để lấy tài liệu gì đó hiển thị ra view thì tất cả chúng ta đơn giản viết một Controller query đến Database để lấy ra tài liệu. Tuy nhiên với Repository pattern như hình trên tất cả chúng ta thấy Repository nó nằm trong lòng, là trung gian giữa Controller và Model. Hiểu đơn giản thì như vậy này, khi có request gọi tới controller, controller gọi tới Repository rồi thằng này gọi tới model lấy data và xử lý, controller lấy tài liệu thì chỉ việc gọi đến thằng này. Lí thuyết thì nói vậy thôi chứ còn để vận dụng nó vào dự án thì tất cả chúng ta sẽ xem ví dụ sau này nhé

2. Sử dụng Repository pattern trong Laravel

Thời điểm hiện tại giả sử mình có một lớp Post và các bạn muốn lấy ra list sản phẩm sắp xếp theo ID giảm dần?

Đề bài khá là easy phải không đơn giản là vào PostController viết một hàm

public function getPost() { $posts = Post::orderBy(‘id’, ‘desc’)->get(); return view(‘post.index’, compact(‘posts’)); }

Vậy là xong easy phải không, Còn nếu viết theo Repository pattern thì tất cả chúng ta sẽ phải tạo thêm một lớp là PostRepository trong một thư mục tên là Repositories, thư mục này trong app/

namespace AppRepositories; use AppModelsPost; class PostRepository { public function getPostById() { return Post::orderBy(‘id’, ‘desc’)->get(); } }

Và trong PostController lúc này tất cả chúng ta sẽ viết

class PostController extends Controller { protected $postRepository; public function __construct(PostRepository $postRepository) { $this->postRepository = $postRepository; } public function getPost() { $posts = $this->postRepository->getPostById(); return view(‘post.index’, compact(‘posts’)); } }

Xem Thêm : Kali Linux là gì? Tại sao hacker thích sử dụng Kali Linux?

Đến đây thì những các bạn sẽ tự hỏi, sao lại phải mất công, đang từ một lớp lấy tài liệu ngon lành lại phải viết thêm một lớp nữa ?? Tài liệu lấy ra cũng thế chả khác gì, mà ban sơ chỉ mất vài dòng code là lấy được, giờ tốn thêm cả chục dòng code nữa, vì sao lại phải như vậy ??.

Mình khi mới tìm hiểu về repository cũng hỏi câu này nhều rồi . Và mình chắc là cũng một cơ số bạn nữa khi mới tìm hiểu về repository đã và đang từng tự có thắc mắc này.

Các bạn có thấy không, Theo phong cách viết không dùng repository thì Controller sẽ gắn chặt và thao tác làm việc trực tiếp mới model. Nếu lúc mà Model có sự thay đổi hay tái cấu trúc bảng gì đó ví dụ như cột title ở bảng posts tất cả chúng ta cần thay lại là title_post chẳng hạn thì tất cả chúng ta sẽ gặp rối rắm khi phải tìm code trong Controller xem nơi đâu dùng đến chỗ đó để sửa. Hoặc đớn đau hơn là, nhu cầu khách hàng thay đổi vào cái ngày trời nắng to ông ấy yêu cầu tất cả chúng ta lấy theo ID giảm dần thế kia, rồi vào trong 1 ngày mưa to ông ấy lại yêu cầu lấy theo lượt view giảm dần . Biết làm thế nào được phải chiều ý khách hàng thôi.

Easy thôi, vào Controller tìm nơi đâu orderBy ID desc sửa thành orderBy view desc là xong. Nhưng vấn đề ở một dự án tất cả chúng ta sẽ sử dụng function đó nhiều lần và có thể là trong nhiều Class khác nhau. Khi đó thì tất cả chúng ta sẽ phải lần mò các Class trong Controller xem nơi đâu có để sửa như vậy thì quá mất thời kì, chưa tính trong những khi sửa không may xóa nhầm hay thêm bớt gì đó trong code hoặc sửa thiếu một vài chỗ, rồi lại ngồi mò bug thì rất là phiền toái. Lúc này đấy là lúc Repository phát huy tác dụng.

Khi viết theo repository thì đơn giản các bạn chỉ có vào Repositories vừa tạo lúc nãy tìm chỗ cần sửa, chỉ có sửa một chỗ, các controller gọi và sử dụng repository này cũng sẽ thay đổi như mình mong muốn. Đến đây các bạn khai mạc thấy repository có ích rồi phải không.

Chưa hết đâu. Tiếp nhé, giờ không nắng cũng không mưa nữa rồi, trời khai mạc có gió thì ông khách hàng kia lại đưa ra yêu cầu là dùng MongoDB hoặc Redis để lưa tài liệu . Thôi đành chiều ý ông kia vậy. Tất cả chúng ta sẽ phải tìm PostRepository vừa rồi và đổi lại thành các PostRepositoryRedis hay PostRepositoryMongo… Ok, không sao sửa thôi,sửa xong vài ngày thì thì ông kia lại không lại muốn quay trở lại như cũ. Đến đây là có vấn đề rồi. Vậy giải pháp là gì?

Để giải quyết và xử lý vấn đề trên tất cả chúng ta sẽ tạo ra một Interface chung cho những loại repositories. Để làm được điều này chúng ra sẽ tạo thêm một thư mục là Contracts và bên trong tạo thêm một thư mục tên là Repositories để viết Interface chung như đã nói trên vào đó, sau đó tạo một interface tên là PostRepositoryInterface ở trong đó. Tên mình đặt kia là không bắt buộc nhé các chúng ta có thể đặt tên khác. Hoặc viết thư mục Contracts bên trong thư mục Repositories tạo ban sơ cũng được. Tất nhiên là với một dự án thì tất cả chúng ta phải xây dựng nhiều Interface ví dụ này mình xây dựng cho Post. Ví dụ một blog thì tất cả chúng ta còn phải xây dựng Interface cho Tag, Question… các Interface này sẽ đặt hết trong AppContractsRepositories nhé.

namespace AppContractsRepositories; interface PostRepositoryInterface { public function getPostById(); … }

Và lúc bấy giờ tất cả chúng ta đã có một interface như một khuôn mẫu chúng để cho những Repositories ở trên implement. Nếu trong project tất cả chúng ta có không chỉ PostRepositoryInterface mà còn có những Interface khác ví như TagRepositoryInterface, QuestionRepositoryInterface. Và tất cả chúng ta nhận ra là trong các Interface này còn có những function tương tự nhau như all(), update(), create()…. Các function mà Interface nào thì cũng thấy có thì những bạn nên xây dựng một Interface chung để khai báo các hàm chung trong đó, và lúc này PostRepositoryInterface, TagRepositoryInterface, QuestionRepositoryInterface sẽ extend từ cái Interface chung vừa nói trên đặt nó là AbstractRepositoryInterface

namespace AppContractsRepositories; interface AbstractRepositoryInterface { public function model(); public function all(); public function store(array $data); public function show($id); public function edit($id); …. }

Và nếu cần một function riêng nào đó không có trong AbstractRepositoryInterface thì tất cả chúng ta chỉ có khai báo thêm trong các Interface extend

namespace AppContractsRepositories; interface PostRepositoryInterface extends AbstractRepositoryInterface { public function pending($id); public function getTags($id); ….. }

Lúc này thì PostRepository tất cả chúng ta vừa viết lúc nãy sẽ implements từ PostRepositoryInterface sẽ phải có chút thay đổi như sau

Xem Thêm : Khắc phục sự cố “Enter Network credentials” trên Windows – Phần 1

namespace AppRepositories; ​ use AppModelsPost; ​ class PostRepository implements PostRepositoryInterface { { //override public function getPostById() { return Post::orderBy(‘id’, ‘desc’)->get(); } }

Redis hay Mongo thì tương tự cũng sẽ implements từ PostRepositoryInterface. Và lúc bấy giờ trong PostsController tất cả chúng ta sẽ thay đổi

class PostsController extends Controller { protected $postRepository; public function __construct(PostRepositoryInterface $postRepository) { $this->PostRepository = $postRepository; } public function getPost() { $post = $this->postRepository->getPostById(); return $post; } }

Nhớ thêm namspaces PostRepositoryInterface nữa nhé.

Các bạn có nhận ra điều gì không, khi tất cả chúng ta thay đổi PostsController thế kia thì khi chạy chắc chắc sẽ bị báo lỗi vì PostRepositoryInterface là một Interface và tất nhiên Interface thì không thể tạo instance được, tất cả chúng ta không thể inject Interface vào Controller. Tuy nhiên với Laravel thì được đấy, với Service container nó có thể giúp tất cả chúng ta bind một interface vào trong 1 implement của nó. Các chúng ta có thể tìm hiểu Service container và Denpendency Injection để nắm vững hơn các thao tác làm việc của nó nhé.

Tiếp theo tất cả chúng ta phải vào thư mục Providers và tìm về AppServiceProvider để đăng kí. Trong phương thức register() tất cả chúng ta sẽ thêm.

public function register() { $this->app->bind( ‘AppContractsRepositoriesPostRepositoryInterface’, ‘AppRepositoriesPostRepository’ ); }

Như vậy là tất cả chúng ta đã đăng kí xong và có thể inject PostRepositoryInterface trong PostController. Nếu dự án tất cả chúng ta cần bind nhiều Interface thì tốt nhất là nên tạo ra một file riêng trong app/Providers chứ không nhất thiết phải dùng AppServiceProvider. Nếu dung cách tạo ra file mới, thì phải khai báo file đó config/app.php và thêm vào providers nhé

‘providers’ => [ … AppProvidersRepositoryServiceProvider::class, ],

Quay trở lại với PostController giờ thì PostController của tất cả chúng ta sẽ chỉ thao tác làm việc với PostRepositoryInterface, các bạn đã thấy lợi ích của Repository Pattern rồi chứ. Trong PostRepositoryInterface tất cả chúng ta sẽ xây dựng dựng những phương thức chung cho những Repostories implements để thực hiện chúng, trong Controller thì tất cả chúng ta sẽ tiến hành gọi như trên để lấy tài liệu.

Vậy là qua bài này tôi đã giới thiệu xong cho những bạn về Repository Pattern trong Laravel. Hy vọng có thể giúp các bạn đang muốn tìm hiểu và muốn clean code có thể phần nào hiểu được và vận dụng.

link tham khảo:

https://viblo.asia/p/laravel-design-patterns-series-repository-pattern-part-3-ogBG2l1ZRxnL https://viblo.asia/p/tim-hieu-ve-service-container-trong-laravel-Qbq5QLw3lD8 http://phpviet.net/repository-pattern-trong-laravel/

You May Also Like

About the Author: v1000