maarsson / laravel-repository
Laravel 8 完整仓库模式
Requires
- php: ^8.1
- laravel/framework: ^9.0|^10.0
README
此包为您的 Laravel 项目添加可扩展的仓库模式。
尽管使用仓库模式而不是 Eloquent 模型可能是一个过时的想法,但您可以使用此包内建的一组函数使您的 Laravel 项目的代码更加整洁。
安装
- 将包添加到您的 Laravel 项目中:
composer require maarsson/laravel-repository
- 发布配置文件
php artisan vendor:publish --tag=repository-config
用法
-
为现有的 Eloquent 模型创建仓库:
php artisan make:repository 'YourModel'
。 -
将模型名称添加到
config/repository.php
'models' => [ 'YourModel', ],
-
在代码中使用依赖注入
use App\Interfaces\YourModelRepositoryInterface; class TestController extends Controller { private $repository; public function __construct(YourModelRepositoryInterface $repository) { $this->repository = $repository; } }
-
可选地,您可以向仓库添加自定义方法
class YourModelRepository extends AbstractEloquentRepository implements YourModelRepositoryInterface { public function doSomeConverting() { // your code here } }
以及接口类
interface YourModelRepositoryInterface { public function doSomeConverting(); }
方法
检索实体
从数据库中检索所有实体
$collection = $this->repository->all();
按 ID 检索实体
$entity = $this->repository->find(3);
按特定列检索实体
$collection = $this->repository->findBy('title', 'Music');
检索第一个或最后一个实体(按其时间戳)
$entity = $this->repository->first(); $entity = $this->repository->last();
您还可以指定要检索的列
$collection = $this->repository->all('id', 'title'); $collection = $this->repository->find(3, 'id', 'title'); $entity = $this->repository->first('id', 'title'); $entity = $this->repository->last('id', 'title');
检索实体数量
$count = $this->repository->count();
创建实体
$entity = $this->repository->create([ 'title' => 'Music', 'price' => 12.9, ]);
更新实体
按 ID 更新实体
$entity = $this->repository->update( 3, // the id of the entity to be updated [ 'title' => 'Music', 'price' => 12.9, ] );
删除实体
按 ID 删除实体
$this->repository->delete(3);
按 where 闭包批量删除实体
$this->repository->deleteWhere('value', '<', 100);
分页
Laravel 的分页可以应用于查询,甚至可以与其他查询组合。
// simple pagination $this->repository ->paginate($per_page = 15); // pagination on ordered result $this->repository ->orderBy('name') ->paginate($per_page = 15);
获取器:自定义过滤和排序
可以使用获取器类轻松过滤或排序实体。在请求中未与获取器类中的匹配函数对应的过滤键和排序方法将被忽略。
-
为现有的仓库创建获取器类:
php artisan make:getter 'YourModel'
。 -
将
Maarsson\Repository\Traits\GetterableTrait
特性添加到模型仓库namespace App\Repositories; use Maarsson\Repository\Traits\GetterableTrait; class YourModelRepository extends AbstractEloquentRepository implements CustomerRepositoryInterface { use GetterableTrait; }
-
将必要的过滤方法添加到创建的
YourModelGetter
类。过滤方法名称必须是驼峰式命名,并以Filter
结尾protected function nameFilter(string|null $searchString): \Illuminate\Database\Eloquent\Builder { return $this->builder->where('name', 'LIKE', '%' . $searchString . '%'); }
-
使用查询中的
filter[]
参数获取过滤后的集合// HTTP GET ///yourmodel?filter[name]=foo public function index(\App\Filters\YourModelGetter $getter) { return $this->repository ->filter($getter) ->get(); }
-
将必要的排序方法添加到创建的
YourModelGetter
类。排序方法名称必须是驼峰式命名,并以Sorter
结尾protected function relatedModelDateSorter(): \Illuminate\Database\Eloquent\Builder { return RelatedModel::select('date') ->whereColumn('this_model_column', 'related_table.column'); }
-
使用查询中的
sort_by
参数获取排序后的集合// HTTP GET ///yourmodel?sort_by=related_model_date public function index(\App\Filters\YourModelGetter $getter) { return $this->repository ->order($getter) ->get(); }
简化的过滤、排序和分页
通过辅助方法获取过滤、排序和分页的结果。
// HTTP GET ///yourmodel?filter[name]=foo&page=5&per_page=20&sort_by=related_model_date&sort_order=desc public function index(\App\Filters\YourModelGetter $getter) { return $this->repository ->filter($getter) ->order() ->paginate(); }
以下请求参数被考虑
filter[]
默认:null
page
默认:1
per_page
默认:20
sort_by
默认:'id'
sort_order
默认:'asc'
属性(和关系)过滤
使用属性过滤特性,您可以控制要检索的模型属性,包括关系(及其属性)。
-
将
Maarsson\Repository\Traits\EloquentAttributeFilterTrait
特性添加到 Eloquent 模型namespace App\Models; use Maarsson\Repository\Traits\EloquentAttributeFilterTrait; class YourModel extends Model { use EloquentAttributeFilterTrait; }
-
使用简单的点分隔符数组通过
withAttributes()
方法获取完全控制添加的属性和关系。在此示例中,您还可以看到如何将其与分页结合使用。// HTTP GET ///yourmodel?filter[name]=foo&page=5&per_page=20&sort_by=related_model_date&sort_order=desc public function index(\App\Filters\YourModelGetter $getter) { return $this->repository ->filter($getter) ->order() ->paginate(); ->through( fn ($item) => $item->withAttributes([ 'id', 'name', // a model property 'finalPrice', // even a model accessor 'users' // a relation (with all of its attributes) 'users.posts:id,title', // a relations relation (with limited attributes) ]) ); }
使用 Eloquent Builder 方法
某些构建器方法可以直接使用。注意查询末尾的获取器方法的使用。
复杂的 where 查询
$this->repository ->where('value', '<', 100) ->get(); $this->repository ->where('value', '>', 50) ->orWhere('value', '<', 100) ->get();
排序结果
$this->repository->orderBy('title', 'desc')->get();
与软删除实体一起工作
$this->repository->withTrashed()->get(); $this->repository->onlyTrashed()->get();
与关系一起工作
$this->repository->with('authors')->get();
访问原生 Eloquent Builder
$this->repository->builder() ->whereIn('id', [1,2,3]); ->limit(5); ->offset(10); ->toSql();
事件
在某些情况下自动触发的事件
创建事件
- 在实体创建之前,会触发
\App\Events\YourModelIsCreatingEvent::class
- 其中,
$event->attributes
属性包含创建的数据数组。
- 其中,
- 在实体创建之后,会触发
\App\Events\YourModelWasCreatedEvent::class
- 其中,
$event->model
属性包含已创建的实体, - 且
$event->attributes
属性包含创建的数据数组。
- 其中,
更新事件
- 在实体更新之前,会触发
\App\Events\YourModelIsUpdatingEvent::class
- 其中,
$event->model
属性包含原始实体, - 且
$event->attributes
属性包含更新的数据数组。
- 其中,
- 在实体更新之后,会触发
\App\Events\YourModelWasUpdatedEvent::class
- 其中,
$event->model
属性包含已更新的实体, - 且
$event->attributes
属性包含更新的数据数组。
- 其中,
删除事件
- 在实体删除之前,会触发
\App\Events\YourModelIsDeletingEvent::class
- 其中,
$event->model
属性包含原始实体。
- 其中,
- 在实体删除之后,会触发
\App\Events\YourModelWasDeletedEvent::class
- 其中,
$event->model
属性包含已删除的实体。
- 其中,
监听器
为具有相同命名约定的事件自动设置事件监听器
YourModelIsCreatingListener
监听YourModelIsCreatingEvent
YourModelWasCreatedListener
监听YourModelWasCreatedEvent
等等。
如果某个监听器中 handle()
方法在事件之前返回 false
,将禁止执行该操作。
许可证
此软件包是开源软件,根据 MIT 许可证 许可。