ratno / laravel-repositories
使用原生 Eloquent 函数的 Laravel 仓库
README
注意!这不是另一个基类,其中有一些方法试图作为 Eloquent 的替代品。这是一个实现,您可以在自定义类上使用所有 Eloquent 特性!
在 Laravel 中使用仓库可能有些令人困惑。如果您创建作为仓库工作的自定义类,您将无法再使用 Eloquent,这是 Laravel 最优秀的特性之一。这就是为什么我正在寻找另一种在 Laravel 中使用仓库模式的方法。我想到了这个方法,并认为我应该分享它。
安装
只需通过 Composer 安装
composer require mratiebatie/laravel-repositories
安装后,您就可以开始使用 Laravel 的仓库模式了。
创建仓库类
此包提供了一个新的 Artisan 命令来创建仓库类。所有类都将生成在 App\Repositories
文件夹中,如果此文件夹不存在,它将被自动生成。
php artisan make:repository ProductRepository
您可以使用 --model
选项来定义将与该仓库相关联的 Eloquent 模型。
php artisan make:repository ProductRepository --model=App\\Product
请记住写出您的模型 完整命名空间,使用 '\\' 作为分隔符。
示例
在这个示例中,我假设您已经有一个名为 Product 的模型。使用以下命令
php artisan make:repository ProductRepository --model=App\\Models\\Product
<?php namespace App\Repositories; use MrAtiebatie\Repository; use App\Models\Product; class ProductRepository { use Repository; /** * The model being queried. * * @var Model */ protected $model; /** * Constructor */ public function __construct() { // setup the model $this->model = app(Product::class); } }
使用 Repository
特性和 protected $model
属性来实现魔法。当您在您的仓库上调用 Eloquent 方法时,此调用将回退到您的模型。
因此,所有 Eloquent 方法,如 where
、all
、find
或您的自定义作用域都可在您的仓库中可用。
初始化 $model
属性的建议方法是使用 IoC 容器。这样,您就可以在编写单元测试时替换模型为 Mock 对象。
<?php namespace App\Repositories; use MrAtiebatie\Repository; use App\Models\Product; class ProductRepository { use Repository; /** * The model being queried. * * @var Model */ protected $model; /** * Constructor */ public function __construct() { // setup the model $this->model = app(Product::class); } /** * Find published products by SKU * * @param {int} $sku * * @return {Product} */ public function findBySku(int $sku): Product { // using 'whereIsPublished' and 'whereSku' scopes // defined on the Product model return $this->whereIsPublished(1) ->whereSku($sku) ->first(); } }
<?php /** * In your routes/web.php */ Route::get('/', function (\App\Repositories\ProductRepository $productRepo) { // Use any Eloquent feature directly $productRepo->all()->dd(); // Use your custom repository methods echo $productRepo->findBySku(12345)->name; // You can even query relations echo $productRepo->first()->category; });
我将以下内容作为经验法则
- 当您正在链式调用超过 2 个 Eloquent 方法时,为它创建一个仓库方法。这适用于所有类型的操作,如关系、查询作用域等。
创建外观
在我们之前的示例中,我们使用依赖注入来检索我们的仓库。
如果您想像使用模型一样使用您的仓库,您需要创建一个外观。
- 首先,创建您的外观,例如在
app/Facades/ProductRepository
中。
<?php namespace App\Facades; use Illuminate\Support\Facades\Facade; class ProductRepository extends Facade { protected static function getFacadeAccessor() { return 'ProductRepository'; } }
- 然后,在您的
app/Providers/AppServiceProvider.php
中,注册您的外观。
<?php namespace App\Providers; use App\Repositories\ProductRepository; use Illuminate\Support\ServiceProvider; class AppServiceProvider extends ServiceProvider { /** * Register any application services. * * @return void */ public function register() { $this->app->bind('ProductRepository', function () { return new ProductRepository(); }); } /** * Bootstrap any application services. * * @return void */ public function boot() { // } }
- 最后一步,将此别名添加到您的
config/app.php
文件中。
'ProductRepository' => App\Facades\ProductRepository::class,
现在,我们的 routes/web.php
示例将如下所示
<?php /** * In your routes/web.php */ use App\Facades\ProductRepository; Route::get('/', function () { // Use any Eloquent feature directly ProductRepository::all()->dd(); // Use your custom repository methods echo ProductRepository::findBySku(12345)->name; // You can even query relations echo ProductRepository::first()->category; });
致谢
Sjors van Dongen (sitesjors@hotmail.com)
Yannick Leone (yannick.leone@gmail.com)