mratiebatie / laravel-repositories
使用原生 Eloquent 函数的 Laravel 仓库。
Requires
- illuminate/console: ^5.0|^6.0|^7.0|^8.0
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 方法时,请为它创建一个仓库方法。这适用于所有类型的方法、关系、查询作用域等。
创建外观
在我们的上一个例子中,我们使用了依赖注入来检索我们的仓库。
如果您想像使用模型一样使用您的仓库,您需要创建一个 Facade。
- 首先,创建您的 Facade,例如在
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
中注册您的 Facade
<?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)