ck-laravel-packages / repository
CargoKing Laravel 8 - 数据库层的仓库
该软件包的规范仓库似乎已丢失,因此软件包已被冻结。
Requires
- php: >=7.4.0
- illuminate/config: ~5.0|~6.0|~7.0|^8.0
- illuminate/console: ~5.0|~6.0|~7.0|^8.0
- illuminate/database: ~5.0|~6.0|~7.0|^8.0
- illuminate/filesystem: ~5.0|~6.0|~7.0|^8.0
- illuminate/http: ~5.0|~6.0|~7.0|^8.0
- illuminate/pagination: ~5.0|~6.0|~7.0|^8.0
- illuminate/support: ~5.0|~6.0|~7.0|^8.0
- illuminate/validation: ~5.0|~6.0|~7.0|^8.0
Suggests
- league/fractal: Required to use the Fractal Presenter (0.12.*).
- prettus/laravel-validation: Required to provide easy validation with the repository (1.1.*)
- robclancy/presenter: Required to use the Presenter Model (1.3.*)
README
Laravel 5 Repositories 用于抽象数据层,使我们的应用程序更灵活,便于维护。
查看版本:1.0.* / 2.0.*
迁移到:2.0 / 2.1
您想了解更多有关仓库模式的信息吗? 阅读这篇精彩文章。
目录
安装
Composer
执行以下命令以获取软件包的最新版本:
composer require prettus/l5-repository
Laravel
>= laravel5.5
ServiceProvider 将自动附加
其他
在您的 config/app.php
文件中,将 Prettus\Repository\Providers\RepositoryServiceProvider::class
添加到 providers
数组的末尾。
'providers' => [
...
Prettus\Repository\Providers\RepositoryServiceProvider::class,
],
如果使用 Lumen
$app->register(Prettus\Repository\Providers\LumenRepositoryServiceProvider::class);
发布配置
php artisan vendor:publish --provider "Prettus\Repository\Providers\RepositoryServiceProvider"
方法
Prettus\Repository\Contracts\RepositoryInterface
- all($columns = array('*'))
- first($columns = array('*'))
- paginate($limit = null, $columns = ['*'])
- find($id, $columns = ['*'])
- findByField($field, $value, $columns = ['*'])
- findWhere(array $where, $columns = ['*'])
- findWhereIn($field, array $where, $columns = [*])
- findWhereNotIn($field, array $where, $columns = [*])
- findWhereBetween($field, array $where, $columns = [*])
- create(array $attributes)
- update(array $attributes, $id)
- updateOrCreate(array $attributes, array $values = [])
- delete($id)
- deleteWhere(array $where)
- orderBy($column, $direction = 'asc');
- with(array $relations);
- has(string $relation);
- whereHas(string $relation, closure $closure);
- hidden(array $fields);
- visible(array $fields);
- scopeQuery(Closure $scope);
- getFieldsSearchable();
- setPresenter($presenter);
- skipPresenter($status = true);
Prettus\Repository\Contracts\RepositoryCriteriaInterface
- pushCriteria($criteria)
- popCriteria($criteria)
- getCriteria()
- getByCriteria(CriteriaInterface $criteria)
- skipCriteria($status = true)
- getFieldsSearchable()
Prettus\Repository\Contracts\CacheableInterface
- setCacheRepository(CacheRepository $repository)
- getCacheRepository()
- getCacheKey($method, $args = null)
- getCacheMinutes()
- skipCache($status = true)
Prettus\Repository\Contracts\PresenterInterface
- present($data);
Prettus\Repository\Contracts\Presentable
- setPresenter(PresenterInterface $presenter);
- presenter();
Prettus\Repository\Contracts\CriteriaInterface
- apply($model, RepositoryInterface $repository);
Prettus\Repository\Contracts\Transformable
- transform();
使用方法
创建一个模型
创建您的模型,但定义可以由输入表单数据填充的属性非常重要。
namespace App;
class Post extends Eloquent { // or Ardent, Or any other Model Class
protected $fillable = [
'title',
'author',
...
];
...
}
创建一个仓库
namespace App;
use Prettus\Repository\Eloquent\BaseRepository;
class PostRepository extends BaseRepository {
/**
* Specify Model class name
*
* @return string
*/
function model()
{
return "App\\Post";
}
}
生成器
通过生成器轻松创建您的仓库。
配置
您必须首先配置仓库文件的存储位置。默认情况下是 "app" 文件夹和命名空间 "App"。请注意,paths
数组中的值实际上既用作 命名空间 也用作文件路径。不过,生成过程中会自动处理正斜杠和反斜杠。
...
'generator'=>[
'basePath'=>app()->path(),
'rootNamespace'=>'App\\',
'paths'=>[
'models' => 'Entities',
'repositories' => 'Repositories',
'interfaces' => 'Repositories',
'transformers' => 'Transformers',
'presenters' => 'Presenters',
'validators' => 'Validators',
'controllers' => 'Http/Controllers',
'provider' => 'RepositoryServiceProvider',
'criteria' => 'Criteria',
]
]
您可能想将项目文件夹的根目录放在 "app" 之外,并添加另一个命名空间,例如
...
'generator'=>[
'basePath' => base_path('src/Lorem'),
'rootNamespace' => 'Lorem\\'
]
此外,您可能希望自定义生成的类保存的位置。可以通过编辑 paths
节点来实现。例如
'generator'=>[
'basePath'=>app()->path(),
'rootNamespace'=>'App\\',
'paths'=>[
'models'=>'Models',
'repositories'=>'Repositories\\Eloquent',
'interfaces'=>'Contracts\\Repositories',
'transformers'=>'Transformers',
'presenters'=>'Presenters'
'validators' => 'Validators',
'controllers' => 'Http/Controllers',
'provider' => 'RepositoryServiceProvider',
'criteria' => 'Criteria',
]
]
命令
要生成您的模型所需的所有内容,请运行此命令
php artisan make:entity Post
这将创建控制器、验证器、模型、仓库、演示者和转换器类。它还会创建一个新的服务提供者,该提供者将用于将 Eloquent 仓库与其对应的仓库接口绑定。要加载它,只需将其添加到您的 AppServiceProvider@register 方法中
$this->app->register(RepositoryServiceProvider::class);
您也可以从 `
repository`
命令传递选项,因为该命令只是一个包装器。
要为您的 Post 模型生成仓库,请使用以下命令
php artisan make:repository Post
要为具有 Blog 命名空间的 Post 模型生成仓库,请使用以下命令
php artisan make:repository "Blog\Post"
添加可填充字段
php artisan make:repository "Blog\Post" --fillable="title,content"
要直接通过命令添加验证规则,需要传递 --rules
选项并创建迁移
php artisan make:entity Cat --fillable="title:string,content:text" --rules="title=>required|min:2, content=>sometimes|min:10"
该命令还会创建您的基本 RESTful 控制器,所以只需将此行添加到您的 routes.php
文件中,您将拥有基本的 CRUD
Route::resource('cats', CatsController::class);
运行命令时,您将在您设置的默认文件夹中创建 "Entities" 文件夹和 "Repositories" 文件夹。
现在已完成,您仍需要绑定其实际仓库的接口,例如在您的 Repositories 服务提供者中。
App::bind('{YOUR_NAMESPACE}Repositories\PostRepository', '{YOUR_NAMESPACE}Repositories\PostRepositoryEloquent');
然后使用
public function __construct({YOUR_NAMESPACE}Repositories\PostRepository $repository){
$this->repository = $repository;
}
或者,您可以使用 artisan 命令来自动绑定。
php artisan make:bindings Cats
使用方法
namespace App\Http\Controllers;
use App\PostRepository;
class PostsController extends BaseController {
/**
* @var PostRepository
*/
protected $repository;
public function __construct(PostRepository $repository){
$this->repository = $repository;
}
....
}
在仓库中查找所有结果
$posts = $this->repository->all();
在仓库中带分页查找所有结果
$posts = $this->repository->paginate($limit = null, $columns = ['*']);
通过 id 查找结果
$post = $this->repository->find($id);
隐藏模型的属性
$post = $this->repository->hidden(['country_id'])->find($id);
仅显示模型的具体属性
$post = $this->repository->visible(['id', 'state_id'])->find($id);
加载模型的关联关系
$post = $this->repository->with(['state'])->find($id);
通过字段名查找结果
$posts = $this->repository->findByField('country_id','15');
通过多个字段查找结果
$posts = $this->repository->findWhere([
//Default Condition =
'state_id'=>'10',
'country_id'=>'15',
//Custom Condition
['columnName','>','10']
]);
通过一个字段中的多个值查找结果
$posts = $this->repository->findWhereIn('id', [1,2,3,4,5]);
通过一个字段中排除多个值查找结果
$posts = $this->repository->findWhereNotIn('id', [6,7,8,9,10]);
使用自定义作用域查找所有结果
$posts = $this->repository->scopeQuery(function($query){
return $query->orderBy('sort_order','asc');
})->all();
在仓库中创建新条目
$post = $this->repository->create( Input::all() );
在仓库中更新条目
$post = $this->repository->update( Input::all(), $id );
在仓库中删除条目
$this->repository->delete($id)
通过多个字段删除仓库中的条目
$this->repository->deleteWhere([
//Default Condition =
'state_id'=>'10',
'country_id'=>'15',
])
创建一个标准
使用命令
php artisan make:criteria My
标准是按照您的需求应用特定条件以更改查询的仓库。您可以在您的仓库中添加多个标准。
use Prettus\Repository\Contracts\RepositoryInterfaceRepository;
use Prettus\Repository\Contracts\CriteriaInterface;
class MyCriteria implements CriteriaInterface {
public function apply($model, RepositoryInterfaceRepository $repository)
{
$model = $model->where('user_id','=', Auth::user()->id );
return $model;
}
}
在控制器中使用标准
namespace App\Http\Controllers;
use App\PostRepository;
class PostsController extends BaseController {
/**
* @var PostRepository
*/
protected $repository;
public function __construct(PostRepository $repository){
$this->repository = $repository;
}
public function index()
{
$this->repository->pushCriteria(new MyCriteria1());
$this->repository->pushCriteria(MyCriteria2::class);
$posts = $this->repository->all();
...
}
}
从标准获取结果
$posts = $this->repository->getByCriteria(new MyCriteria());
在仓库中设置默认标准
use Prettus\Repository\Eloquent\BaseRepository;
class PostRepository extends BaseRepository {
public function boot(){
$this->pushCriteria(new MyCriteria());
// or
$this->pushCriteria(AnotherCriteria::class);
...
}
function model(){
return "App\\Post";
}
}
跳过仓库中定义的标准
在其它链式方法之前使用 skipCriteria
$posts = $this->repository->skipCriteria()->all();
弹出标准
使用 popCriteria
来移除标准
$this->repository->popCriteria(new Criteria1());
// or
$this->repository->popCriteria(Criteria1::class);
使用请求标准
RequestCriteria 是标准标准实现。它允许过滤器通过请求中发送的参数在仓库中执行。
您可以执行动态搜索,过滤数据并自定义查询。
要在您的仓库中使用标准,您可以在仓库的 boot 方法中添加新的标准,或者在控制器中直接使用,以便过滤出少数请求。
在仓库中启用
use Prettus\Repository\Eloquent\BaseRepository;
use Prettus\Repository\Criteria\RequestCriteria;
class PostRepository extends BaseRepository {
/**
* @var array
*/
protected $fieldSearchable = [
'name',
'email'
];
public function boot(){
$this->pushCriteria(app('Prettus\Repository\Criteria\RequestCriteria'));
...
}
function model(){
return "App\\Post";
}
}
请记住,您需要定义模型中哪些字段是可以搜索的。
在您的仓库中设置 $fieldSearchable 为要搜索的字段名称或字段的关系。
protected $fieldSearchable = [
'name',
'email',
'product.name'
];
您可以设置用于执行查询的条件类型,默认条件是 "="
protected $fieldSearchable = [
'name'=>'like',
'email', // Default Condition "="
'your_field'=>'condition'
];
在控制器中启用
public function index()
{
$this->repository->pushCriteria(app('Prettus\Repository\Criteria\RequestCriteria'));
$posts = $this->repository->all();
...
}
标准示例
通过请求获取所有数据而不进行筛选
http://prettus.local/users
[
{
"id": 1,
"name": "John Doe",
"email": "john@gmail.com",
"created_at": "-0001-11-30 00:00:00",
"updated_at": "-0001-11-30 00:00:00"
},
{
"id": 2,
"name": "Lorem Ipsum",
"email": "lorem@ipsum.com",
"created_at": "-0001-11-30 00:00:00",
"updated_at": "-0001-11-30 00:00:00"
},
{
"id": 3,
"name": "Laravel",
"email": "laravel@gmail.com",
"created_at": "-0001-11-30 00:00:00",
"updated_at": "-0001-11-30 00:00:00"
}
]
在仓库中进行研究
http://prettus.local/users?search=John%20Doe
或者
http://prettus.local/users?search=John&searchFields=name:like
或者
http://prettus.local/users?search=john@gmail.com&searchFields=email:=
或者
http://prettus.local/users?search=name:John Doe;email:john@gmail.com
或者
http://prettus.local/users?search=name:John;email:john@gmail.com&searchFields=name:like;email:=
[
{
"id": 1,
"name": "John Doe",
"email": "john@gmail.com",
"created_at": "-0001-11-30 00:00:00",
"updated_at": "-0001-11-30 00:00:00"
}
]
默认情况下,RequestCriteria 使用 OR 比较运算符对每个查询参数进行查询。 http://prettus.local/users?search=age:17;email:john@gmail.com
上面的例子将执行以下查询
SELECT * FROM users WHERE age = 17 OR email = 'john@gmail.com';
要使用 AND 进行查询,请传递以下参数
http://prettus.local/users?search=age:17;email:john@gmail.com&searchJoin=and
过滤字段
http://prettus.local/users?filter=id;name
[
{
"id": 1,
"name": "John Doe"
},
{
"id": 2,
"name": "Lorem Ipsum"
},
{
"id": 3,
"name": "Laravel"
}
]
排序结果
http://prettus.local/users?filter=id;name&orderBy=id&sortedBy=desc
[
{
"id": 3,
"name": "Laravel"
},
{
"id": 2,
"name": "Lorem Ipsum"
},
{
"id": 1,
"name": "John Doe"
}
]
通过相关表排序
http://prettus.local/users?orderBy=posts|title&sortedBy=desc
查询将类似于以下内容
...
INNER JOIN posts ON users.post_id = posts.id
...
ORDER BY title
...
http://prettus.local/users?orderBy=posts:custom_id|posts.title&sortedBy=desc
查询将类似于以下内容
...
INNER JOIN posts ON users.custom_id = posts.id
...
ORDER BY posts.title
...
按相同排序方式排序多个列
http://prettus.local/users?orderBy=name;created_at&sortedBy=desc
结果将类似于以下内容
[
{
"id": 1,
"name": "Laravel",
"created_at": "-0001-11-29 00:00:00"
},
{
"id": 3,
"name": "Laravel",
"created_at": "-0001-11-28 00:00:00"
},
{
"id": 2,
"name": "John Doe",
"created_at": "-0001-11-30 00:00:00"
}
]
按不同排序方式排序多个列
http://prettus.local/users?orderBy=name;created_at&sortedBy=desc;asc
结果将类似于以下内容
[
{
"id": 3,
"name": "Laravel",
"created_at": "-0001-11-28 00:00:00"
},
{
"id": 1,
"name": "Laravel",
"created_at": "-0001-11-29 00:00:00"
},
{
"id": 2,
"name": "John Doe",
"created_at": "-0001-11-30 00:00:00"
}
]
添加关系
http://prettus.local/users?with=groups
覆盖参数名称
您可以在配置文件 config/repository.php 中更改参数的名称
缓存
轻松为您的仓库添加缓存层
缓存使用
实现 CacheableInterface 接口并使用 CacheableRepository 特性。
use Prettus\Repository\Eloquent\BaseRepository;
use Prettus\Repository\Contracts\CacheableInterface;
use Prettus\Repository\Traits\CacheableRepository;
class PostRepository extends BaseRepository implements CacheableInterface {
use CacheableRepository;
...
}
完成,完成之后您的仓库将被缓存,并且每当创建、修改或删除项目时,仓库缓存将被清除。
缓存配置
您可以在文件 config/repository.php 中更改缓存设置,也可以直接在您的仓库上直接更改。
config/repository.php
'cache'=>[
//Enable or disable cache repositories
'enabled' => true,
//Lifetime of cache
'minutes' => 30,
//Repository Cache, implementation Illuminate\Contracts\Cache\Repository
'repository'=> 'cache',
//Sets clearing the cache
'clean' => [
//Enable, disable clearing the cache on changes
'enabled' => true,
'on' => [
//Enable, disable clearing the cache when you create an item
'create'=>true,
//Enable, disable clearing the cache when upgrading an item
'update'=>true,
//Enable, disable clearing the cache when you delete an item
'delete'=>true,
]
],
'params' => [
//Request parameter that will be used to bypass the cache repository
'skipCache'=>'skipCache'
],
'allowed'=>[
//Allow caching only for some methods
'only' =>null,
//Allow caching for all available methods, except
'except'=>null
],
],
您可以直接在仓库中覆盖这些设置。
use Prettus\Repository\Eloquent\BaseRepository;
use Prettus\Repository\Contracts\CacheableInterface;
use Prettus\Repository\Traits\CacheableRepository;
class PostRepository extends BaseRepository implements CacheableInterface {
// Setting the lifetime of the cache to a repository specifically
protected $cacheMinutes = 90;
protected $cacheOnly = ['all', ...];
//or
protected $cacheExcept = ['find', ...];
use CacheableRepository;
...
}
可缓存的函数是:all、paginate、find、findByField、findWhere、getByCriteria
验证器
需要 prettus/laravel-validator。 composer require prettus/laravel-validator
使用 prettus/laravel-validator
进行简单验证
使用验证器类
创建一个验证器
在下面的示例中,我们为创建和编辑定义了一些规则
use \Prettus\Validator\LaravelValidator;
class PostValidator extends LaravelValidator {
protected $rules = [
'title' => 'required',
'text' => 'min:3',
'author'=> 'required'
];
}
要定义特定规则,请按照以下步骤操作
use \Prettus\Validator\Contracts\ValidatorInterface;
use \Prettus\Validator\LaravelValidator;
class PostValidator extends LaravelValidator {
protected $rules = [
ValidatorInterface::RULE_CREATE => [
'title' => 'required',
'text' => 'min:3',
'author'=> 'required'
],
ValidatorInterface::RULE_UPDATE => [
'title' => 'required'
]
];
}
在仓库中启用验证器
use Prettus\Repository\Eloquent\BaseRepository;
use Prettus\Repository\Criteria\RequestCriteria;
class PostRepository extends BaseRepository {
/**
* Specify Model class name
*
* @return mixed
*/
function model(){
return "App\\Post";
}
/**
* Specify Validator class name
*
* @return mixed
*/
public function validator()
{
return "App\\PostValidator";
}
}
在仓库中定义规则
或者,您可以直接在规则仓库属性中设置您的规则,而不是使用类来定义验证规则,它将产生与 Validation 类相同的效果。
use Prettus\Repository\Eloquent\BaseRepository;
use Prettus\Repository\Criteria\RequestCriteria;
use Prettus\Validator\Contracts\ValidatorInterface;
class PostRepository extends BaseRepository {
/**
* Specify Validator Rules
* @var array
*/
protected $rules = [
ValidatorInterface::RULE_CREATE => [
'title' => 'required',
'text' => 'min:3',
'author'=> 'required'
],
ValidatorInterface::RULE_UPDATE => [
'title' => 'required'
]
];
/**
* Specify Model class name
*
* @return mixed
*/
function model(){
return "App\\Post";
}
}
验证现在已就绪。如果验证失败,将抛出类型为 Prettus\Validator\Exceptions\ValidatorException 的异常
演示者
展示者函数作为对象的包装器和渲染器。
Fractal 演示者
需要 Fractal。 composer require league/fractal
有两种方法来实现展示者,第一种是创建一个 TransformerAbstract 并使用您的展示者类,如 Create a Transformer Class 中所述。
第二种方法是使您的模型实现 Transformable 接口,并使用默认的展示者 ModelFractarPresenter,这会产生相同的效果。
转换器类
使用命令创建转换器
php artisan make:transformer Post
这将生成下面的类。
创建转换器类
use League\Fractal\TransformerAbstract;
class PostTransformer extends TransformerAbstract
{
public function transform(\Post $post)
{
return [
'id' => (int) $post->id,
'title' => $post->title,
'content' => $post->content
];
}
}
使用命令创建展示者
php artisan make:presenter Post
如果尚未创建转换器,命令将提示您创建转换器。
创建展示者
use Prettus\Repository\Presenter\FractalPresenter;
class PostPresenter extends FractalPresenter {
/**
* Prepare data to present
*
* @return \League\Fractal\TransformerAbstract
*/
public function getTransformer()
{
return new PostTransformer();
}
}
在仓库中启用
use Prettus\Repository\Eloquent\BaseRepository;
class PostRepository extends BaseRepository {
...
public function presenter()
{
return "App\\Presenter\\PostPresenter";
}
}
或者在控制器中启用它
$this->repository->setPresenter("App\\Presenter\\PostPresenter");
从模型使用展示者
如果您记录了展示者并在某些时候使用了 skipPresenter()
方法,或者您根本不希望您的结果被展示者自动更改。您可以在您的模型上实现 Presentable 接口,这样您就可以在任何时候展示您的模型。请参见以下内容
在您的模型中实现接口 Prettus\Repository\Contracts\Presentable
和 Prettus\Repository\Traits\PresentableTrait
namespace App;
use Prettus\Repository\Contracts\Presentable;
use Prettus\Repository\Traits\PresentableTrait;
class Post extends Eloquent implements Presentable {
use PresentableTrait;
protected $fillable = [
'title',
'author',
...
];
...
}
现在,您可以单独提交您的模型,看一个示例
$repository = app('App\PostRepository');
$repository->setPresenter("Prettus\\Repository\\Presenter\\ModelFractalPresenter");
//Getting the result transformed by the presenter directly in the search
$post = $repository->find(1);
print_r( $post ); //It produces an output as array
...
//Skip presenter and bringing the original result of the Model
$post = $repository->skipPresenter()->find(1);
print_r( $post ); //It produces an output as a Model object
print_r( $post->presenter() ); //It produces an output as array
您可以在每次访问时跳过展示器,并直接在模型中按需使用它,为此在您的仓库中将 $skipPresenter
属性设置为 true
use Prettus\Repository\Eloquent\BaseRepository;
class PostRepository extends BaseRepository {
/**
* @var bool
*/
protected $skipPresenter = true;
public function presenter()
{
return "App\\Presenter\\PostPresenter";
}
}
模型类
实现接口
namespace App;
use Prettus\Repository\Contracts\Transformable;
class Post extends Eloquent implements Transformable {
...
/**
* @return array
*/
public function transform()
{
return [
'id' => (int) $this->id,
'title' => $this->title,
'content' => $this->content
];
}
}
在仓库中启用
Prettus\Repository\Presenter\ModelFractalPresenter
是为实现 Transformable 的模型提供的默认展示器
use Prettus\Repository\Eloquent\BaseRepository;
class PostRepository extends BaseRepository {
...
public function presenter()
{
return "Prettus\\Repository\\Presenter\\ModelFractalPresenter";
}
}
或者在控制器中启用它
$this->repository->setPresenter("Prettus\\Repository\\Presenter\\ModelFractalPresenter");
跳过仓库中定义的展示器
在所有其他链式方法之前使用 skipPresenter
$posts = $this->repository->skipPresenter()->all();
或者
$this->repository->skipPresenter();
$posts = $this->repository->all();