safiullahsarhandi / laravel-repository
此包用于在 Laravel 中以非常少的代码实现仓储模式
Requires
- php: ^8.0
README
此包用于在 Laravel 中以非常少的代码实现仓储模式。这种实现的背后的思想是允许模块化方法,并使你的项目中的每个实体可重用,同时通过模型绑定、仓储生成器、仓储事件等功能增强你的编码体验。
安装
使用以下命令,你可以将此包添加到你的 Laravel 项目中
composer require safiullahsarhandi/laravel-repository
安装此包后,您需要在项目的 config/app.php 中注册提供者 LaravelRepository\Providers\RepositoryServiceProvider::class,
发布资产
php artisan vendor:publish --tag=repository-config此命令将在config目录中创建repository.php配置文件,该文件将存储此类信息。
<?php
//config/repository.php
return [
/*
* repositories will contain all the repositories namespaces from app/Repositories directory
* and bind Contract and model associated with it
*
*/
'repositories' => [],
];
?>
用法
此包提供了一些命令,可以帮助执行不同的任务,或者可以说使用此包是必需的。
-
如何创建仓储
命令:
php artisan make:repository <path/to/repository> <model>使用此包创建仓储将变得简单。它会在配置文件中注册您的仓储,并在
app\Repositories目录中创建一系列文件,例如php artisan make:repository User/UserRepository User将更新您的app\Repositories文件夹如下并且更新您的配置文件如下
<?php //config/repository.php return [ /* * repositories will contain all the repositories namespaces from app/Repositories directory * and bind Contract and model associated with it * */ 'repositories' => [ App\Repositories\User\UserRepository::class => [ 'model' => App\Models\User::class, 'contract' => App\Repositories\User\UserRepositoryContract::class, ] ], ]; ?> -
创建查询过滤器
过滤器的思想是扩展数据库查询。在调用任何特定仓储时,您将看到以下仓储函数的结构在某种程度上相似,并且包含最小数量的代码。我将在下一节中解释过滤器的实现,以便您熟悉它,但现在是时候检查如何使用给定命令生成查询过滤器了。
命令:
php artisan make:filter <path/to/filter>例如:
php artisan make:filter Api/UserFilter这将在app/Filters/Api/UserFilters.php中生成过滤器这是
make:filter命令的最终输出。<?php namespace App\Filters\Api; use LaravelRepository\Abstracts\Filters; class UserFilter extends Filters { protected $filters = ['search']; public function search($value) { $this->builder->where("status", $value); } }使模型可过滤
在说明如何使用
UserFilter::class与任何仓储之前,我们应该知道在将过滤器绑定到仓储之前需要遵循的基本步骤。我们必须在模型中使用LaravelRepository\Traits\Filterable以便按需过滤任何模型。<?php namespace App\Models; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; use LaravelRepository\Traits\Filterable; class User extends Model { use HasFactory, Filterable; protected $fillable = ['name','email','password']; }如何使用查询过滤器
过滤类应具有与您在
protected $filters属性中注册的相同名称的方法。每次将查询过滤器绑定到仓储时,它都会读取 Laravel 的Illuminate\Support\Request实例并验证 HTTP 请求中参数的可用性。您可以这样做use App\Filters\Api\UserFilter; use App\Repositories\User\UserRepositoryContract; use Illuminate\Support\Facades\Route; //URL looks like "https://:8000/users?search=active" will give you better understanding for filters Route::get('/users', function (UserRepositoryContract $user,UserFilter $filter) { $data = $user->findAll($filter); // under the hood it work like this // User::where(status,'active')->get(); });扩展查询过滤器
有时您想在不暴露任何特定
route中的每个参数的情况下扩展底层过滤器。您可以在过滤器传递到仓储之前以编程方式扩展过滤器。Route::get('/account', function (UserRepositoryContract $user,UserFilter $filter) { // extends request after it has been initialized $filter->extendRequest([ 'user_id' => auth()->id(), ]); $data = $user->findOne($filter); // under the hood it work like this // User::where('user_id',1)->first(); });并且您的
UserFilter::class应该是这样的<?php namespace App\Filters\Api; use LaravelRepository\Abstracts\Filters; class UserFilter extends Filters { protected $filters = ['search','user_id']; public function search($value) { $this->builder->where("status", $value); } public function user_id($value) { $this->builder->where("id", $value); } } -
创建仓储事件
您不能覆盖仓库提供的预定义函数,但有时,或者更确切地说,大多数时候,您需要在执行过程中对特定时间进行筛选或执行任何特定操作。使用直接仓库函数无法实现这一点,因为它们只是与数据交互,并不实现您的业务逻辑。为了实现这一点,您可以将其与
仓库事件绑定。您可以将事件视为类似于 Laravel 监听器。而监听器仅在模型上触发,但在这里,仓库事件仅对仓库可用。命令:
php artisan make:repository-event <path/to/repository-event>例如:使用以下命令
php artisan make:repository-event User/UserRepositoryEvent将在app/Events/User/UserRepositoryEvent.php中创建事件类,并默认包含以下代码片段。<?php namespace App\Events\User; use Illuminate\Database\Eloquent\Model; use LaravelRepository\Contracts\EventContract; class UserRepositoryEvent implements EventContract { public function beforeCreate($repository,array $params = []){} public function created(Model $model){} public function beforeUpdate($repository,array $params = []){} public function updated(Model $model){} public function beforeDelete($repository,mixed $param){} public function deleted(mixed $param){} public function beforeFetch($repository,mixed $params = null){} public function fetched(null|Model $value = null){} }如何使用事件
当您将
事件类与任何仓库绑定时,会调用仓库事件。您可以看到以下所有仓库方法。假设我们想要创建 `订单` 并将用户选择的产品存储在数据库中。这是如何实现的?您可以创建自己的方法并调用它,但我们推荐使用事件;use App\Repositories\Order\OrderRepositoryContract; use App\Events\Order\OrderRepositoryEvent; Route::post('/orders', function (OrderRepositoryContract $order) { // params will be passed using \Illuminate\Support\Request; // for now just take it as an example $params = [ 'customer_email' => 'customer@example.com', 'customer_name' => 'Mark Endrew', 'products' => [ 1 => ['qty' => 1, 'price' => 200 ], 2 => ['qty' => 1, 'price' => 300 ], ] ]; $data = $order->event(OrderRepositoryEvent::class)->create($params); });现在,我们想要将关联到
订单的产品存储在我们的数据库中。因为我们已经调用了create方法,所以我们可以将一些逻辑放在beforeCreate或created中,在App\Events\Order\OrderRepositoryEvent::class。<?php namespace App\Events\Order; use Illuminate\Database\Eloquent\Model; use LaravelRepository\Contracts\EventContract; class OrderRepositoryEvent implements EventContract { private $params; public function beforeCreate($repository,array $params = []) { //you don't need to do this every time // and we don't have another way to access params in created $this->params = $params; } public function created(Model $model) { // store products after order created $products = $this->params['products']; // storing laravel belongsToMany order_products $model->products()->attach($products); // process merchant payment $model->pay(); } }仓库方法

