Laravel Repository Pattern
This post hasn't been updated for 6 years
Repository Pattern rất hữu ích để giữ code rõ ràng, sạch và dễ đọc hơn. Hôm nay mình sẽ giới thiệu cách sử dụng Repository trong Laravel để làm cho controller ngắn gọn và dễ đọc hơn.
Working Without Repositories
Việc sử dụng repositories không phải là một bắt buộc. Bạn có thể hoàn thành rất nhiều thứ trong ứng dụng mà không dùng pattern này. Tuy nhiên nếu không sử dụng repository thì theo thời gian ứng dụng rất khó để test, khó khăn khi bảo trì và thay đổi. Ví dụ xem xét ví dụ sau:
Getting House Listings From a Real Estate Database
House controller
<?php
class HousesController extends BaseController {
public function index()
{
$houses = House::all();
return View::make('houses.index', compact('houses'));
}
public function create()
{
return View::make('houses.create');
}
public function show($id)
{
$house = House::find($id);
return View::make('houses.show', compact('house'));
}
}
Đây là một đoạn code kinh điển sử dụng Eloquent để tương tác với database để liệt kê danh sách nhà đất. Nó hoạt động okie nhưng có thể thấy controller đang phụ thuộc chặt chẽ vào Eloquent. Chúng ta có thể `inject` một repository để dễ dàng sửa đổi và bảo trì sau này.
Working With Repositories
Có một số bước để tạo repository pattern như sau:
1. Create the Repository Folder
Chúng ta tạo thư mục Repositories
trong thư mục app
của ứng dụng.
2. Create Interface
Bước tiếp theo là tạo interface
để tất cả các repository sẽ implement với một namespace
và các phương thức.
<?php
namespace Repositories;
interface HouseRepositoryInterface {
public function selectAll();
public function find($id);
}
3. Create Your Repository
Chúng ta có thể tạo repository để thực thi tất cả các chức năng. Trong file này chúng ta sẽ để tất cả các truy vấn chi tiết với Eloquent hoặc những xử lý phức tạp.
<?php
namespace Repositories;
use House;
class DbHouseRepository implements HouseRepositoryInterface {
public function selectAll()
{
return House::all();
}
public function find($id)
{
return House::find($id);
}
}
4. Create Backend Service Provider
Đối với controller, chúng ta sẽ đánh gợi ý một interface. Chúng ta sẽ sử dụng dependency injection
, nhưng là cách của một interface cơ bản. Nghĩa là chúng ta cần đăng ký interface với Laravel, vì vậy sẽ biết được implementation của interface chúng ta muốn sử dụng. Đầu tiên, chúng ta sử dụng Eloquent implementation, nhưng sau đó chúng ta move sang một file để show cách chúng ta chuyển đổi implementations dễ dàng sử dụng một interface. Chúng ta sẽ đặt Service Provider
này cùng tên namespace như các file khác.
<?php
namespace Repositories;
use IlluminateSupportServiceProvider;
class BackendServiceProvider extends ServiceProvider {
public function register()
{
$this->app->bind('repotutrepositoriesHouseRepositoryInterface', 'repotutrepositoriesDbHouseRepository');
}
}
Đoạn code này cơ bản cho ta thấy controller đánh gợi ý HouseRepositoryInterface
, chúng ta biết cần sử dụng DbHouseRepository
.
5. Update Your Providers Array
Bây giờ chúng ta tạo một Service Provider
thì cần thêm vào provider array
trong app/config/app.php
. Nó có thể trông như thế này:
'providers' => [
'IlluminateFoundationProvidersArtisanServiceProvider',
'IlluminateAuthAuthServiceProvider',
'IlluminateCacheCacheServiceProvider',
'IlluminateSessionCommandsServiceProvider',
'IlluminateFoundationProvidersConsoleSupportServiceProvider',
'IlluminateRoutingControllerServiceProvider',
'IlluminateCookieCookieServiceProvider',
'IlluminateDatabaseDatabaseServiceProvider',
'IlluminateEncryptionEncryptionServiceProvider',
'IlluminateFilesystemFilesystemServiceProvider',
'IlluminateHashingHashServiceProvider',
'IlluminateHtmlHtmlServiceProvider',
'IlluminateLogLogServiceProvider',
'IlluminateMailMailServiceProvider',
'IlluminateDatabaseMigrationServiceProvider',
'IlluminatePaginationPaginationServiceProvider',
'IlluminateQueueQueueServiceProvider',
'IlluminateRedisRedisServiceProvider',
'IlluminateRemoteRemoteServiceProvider',
'IlluminateAuthRemindersReminderServiceProvider',
'IlluminateDatabaseSeedServiceProvider',
'IlluminateSessionSessionServiceProvider',
'IlluminateTranslationTranslationServiceProvider',
'IlluminateValidationValidationServiceProvider',
'IlluminateViewViewServiceProvider',
'IlluminateWorkbenchWorkbenchServiceProvider',
'repotutrepositoriesBackendServiceProvider'
],
6. Update Your Controller for Dependency Injection
Khi controller inject
một implementation của HouseRepositoryInterface
thì chúng đã sẽ remove tất cả các cách gọi Eloquent trực tiếp trong controller và thay thế bằng một phương thức của repository như sau:
<?php
use repotutrepositoriesHouseRepositoryInterface;
class HousesController extends BaseController {
public function __construct(HouseRepositoryInterface $house)
{
$this->house = $house;
}
public function index()
{
$houses = $this->house->selectAll();
return View::make('houses.index', compact('houses'));
}
public function create()
{
return View::make('houses.create');
}
public function show($id)
{
$house = $this->house->find($id);
return View::make('houses.show', compact('house'));
}
}
7. Confirm Routes are Correct
Trong ví dụ này chúng ta tạo một route resource đơn giản như sau:
<?php
/*
|--------------------------------------------------------------------------
| Application Routes
|--------------------------------------------------------------------------
|
| Here is where you can register all of the routes for an application.
| It's a breeze. Simply tell Laravel the URIs it should respond to
| and give it the Closure to execute when that URI is requested.
|
*/
Route::resource('houses', 'HousesController');
Phải chắc chắn rằng namespace
đã được liên kết trong file composer.json . Chú ý rằng đoạn "psr-4":{"repotut\": "app/repotut" }
sẽ bảo composer autoload tất cả các class trong repotut namespace.
{
"name": "laravel/laravel",
"description": "The Laravel Framework.",
"keywords": ["framework", "laravel"],
"license": "MIT",
"require": {
"laravel/framework": "4.2.*"
},
"autoload": {
"classmap": [
"app/commands",
"app/controllers",
"app/models",
"app/database/migrations",
"app/database/seeds",
"app/tests/TestCase.php"
],
"psr-4":{
"repotut\": "app/repotut"
}
},
"scripts": {
"post-install-cmd": [
"php artisan clear-compiled",
"php artisan optimize"
],
"post-update-cmd": [
"php artisan clear-compiled",
"php artisan optimize"
],
"post-create-project-cmd": [
"php artisan key:generate"
]
},
"config": {
"preferred-install": "dist"
},
"minimum-stability": "stable"
}
Đừng quên run composer dump
sau khi sửa file composer.json
.
All Rights Reserved