laravel-repository

1,048 阅读3分钟
原文链接: blog.jybx.me

laravel 学习-安装 l5-repository 依赖

MVC 架构 Model, View, Controller

Model
模型不仅包含数据,而且包含数据代表的逻辑。

View
View 负责根据 Model 中的数据显示用户界面。

Controller
控制器将用户界面和数据模型关联起来,并充当协调运作的角色。它接收各种用户操作,更新数据模型,并用合适的 view 展示结果给用户。

大型网络 Spring

Service 用于标注业务层组件
Controller 用于标注控制层组件
Repository 用于标注数据访问组件
Presenters 用于标注显示逻辑组件

Repository 是 MVC 中衔接 Controller 和 Model 之间的一个纽带。从概念上讲,Repository 是把将数据给封装后的集合并提供给 Controller 的操作。

l5-repository 是一个为 laravel5 提供的数据库抽象层,目的是为了将应用的数据库操作和核心的业务逻辑分离开,保证 controller 的精简。

安装包地址
packagist

安装

执行以下命令以获取最新版本的软件包:

composer require prettus/l5-repository

在你的 config/app.php 将 Prettus\Repository\Providers\RepositoryServiceProvider::class 添加到 providers 数组的末尾:

'providers' => [
    Prettus\Repository\Providers\RepositoryServiceProvider::class,
]

发布资源文件的服务提供者

php artisan vendor:publish --provider 'Prettus\Repository\Providers\RepositoryServiceProvider'

执行结果

Copied File [/vendor/prettus/l5-repository/src/resources/config/repository.php] To [/config/repository.php]
Publishing complete for tag []!

config/ 下,生成一个 repository.php 的配置文件

配置

首先配置存储库文件的存储位置。 默认情况下是 “app” 文件夹和命名空间 “App”。 请注意, paths 数组中的值可以直接用作命名空间和文件路径。

'generator'  => [
   'basePath'      => app_path(),
   'rootNamespace' => 'App\\',
   'paths'         => [
       'models'       => 'Models', // 修改模型目录名
       'repositories' => 'Repositories\\Eloquent', // Eloquent 目录用于存放实现 Repository 接口的抽象类和具体类
       'interfaces'   => 'Repositories\\Contracts', // 接口
       // Transformer 与 Model 层一一对应的, 主要是对返回数据进行封装
       'transformers' => 'Repositories\\Transformers',
       'presenters'   => 'Presenters', // 将相关的显示逻辑封装在不同的 presenter
       'validators'   => 'Repositories\\Validators', // 验证器
       'controllers'  => 'Http/Controllers/Admin',
       'provider'     => 'RepositoryServiceProvider',
       // 将一些可能会在多个接口或者情况下用到的查询条件放到这里
       'criteria'     => 'Repositories\\Criteria',
       'stubsOverridePath' => app_path()
   ]
]

生成模型所需的一切,请运行以下命令:

php artisan make:entity Article // 有提示,需要生成哪些文件,yes | no

这将创建 Controller,Validator,Model,Repository,Presenter 和 Transformer 类。 它还将创建一个新的服务提供程序,用于绑定 Eloquent 存储库及其对应的存储库接口。 要加载它,只需将它添加到您的 AppServiceProvider@register 方法:

$this->app->register(RepositoryServiceProvider::class);

命令

// namespace App\Repositories\Contracts\Blog;
// namespace App\Repositories\Eloquent\Blog;
// 生成 2 个文件
php artisan make:repository "Blog\Post" 

// 添加验证规则,需要传递 --rules 选项并创建迁移
// 该命令还将创建基本 RESTfull 控制器,所以只需将此行添加到 routes.php 文件
php artisan make:entity Cat --fillable="title:string,content:text" --rules="title=>required|min:2, content=>sometimes|min:10"

Route::resource('cats', CatsController::class);

// 生成 transformers  
php artisan make:transformer Post

// namespace App\Presenters; 
// 生成 presenters  
// 还会有一个提示: Would you like to create a Transformer?
php artisan make:presenter Post

// namespace App\Providers;
// 会生成 'repositoryProviderServer.php',并绑定一个post相关的服务  
php artisan make:bindings Post

// namespace App\Repositories\Criteria;
php artisan make:criteria My

Criteria

Criteria 是一个让你可以根据具体的或者一系列复杂的条件来向你的 repository 发起查询的方式,你可以将一些可能会在多个接口或者情况下用到的查询条件放到这里,到达复用的目的,而且可以将复杂的查询条件从你的 controller 中抽离出来,精简代码的同时,也使得各部分之间的耦合更加松散

<?php

namespace App\Repositories\Criteria;

use Prettus\Repository\Contracts\CriteriaInterface;
use Prettus\Repository\Contracts\RepositoryInterface;

/**
 * Class MyCriteria
 * @package namespace App\Repositories\Criteria;
 */
class MyCriteria implements CriteriaInterface
{

    protected $id;

    /**
     * MyCriteria constructor.
     * @param $id
     */
    public function __construct($id)
    {
        $this->id = $id;
    }

    /**
     * Apply criteria in query repository
     *
     * @param                     $model
     * @param RepositoryInterface $repository
     *
     * @return mixed
     */
    public function apply($model, RepositoryInterface $repository)
    {
        return $model->where('id', $this->id);
    }
}

在控制器中使用条件

<?php

namespace App\Http\Controllers\Admin;

use App\Repositories\Criteria\MyCriteria;
use App\Repositories\Contracts\ArticleRepository;

class ArticlesController extends Controller
{

    /**
     * @var ArticleRepository
     */
    protected $repository;

    public function __construct(ArticleRepository $repository)
    {
        $this->repository = $repository;
    }


    /**
     * Display a listing of the resource.
     *
     * @return \Illuminate\Http\Response
     */
    public function index()
    {
        $this->repository->pushCriteria(MyCriteria::class);
        //$this->repository->pushCriteria(new MyCriteria());
        $articles = $this->repository->all();

        return view('articles.index', compact('articles'));
    }
}

Transformer

Transformers 的作用是按照接口的需要来包装你从数据库查询出来的结果,你可以在这里方便的设置你需要哪些字段,每一个字段的数据类型,或者你要联查多个表来组成接口所需要的数据时,你可以在这里利用 eloquent 的 relationship 方便的完成
这是一个第三方的包,需要你用 composer 引入

composer require league/fractal

<?php

namespace App\Repositories\Transformers;

use League\Fractal\TransformerAbstract;
use App\Models\Article;

/**
 * Class ArticleTransformer
 * @package namespace App\Repositories\Transformers;
 */
class ArticleTransformer extends TransformerAbstract
{

    /**
     * Transform the \Article entity
     * @param Article $model
     *
     * @return array
     */
    public function transform(Article $model)
    {
        return [
            'id'         => (int) $model->id,

            /* place your other model properties here */

            'created_at' => $model->created_at,
            'updated_at' => $model->updated_at
        ];
    }
}

在 repository 存储库中设置默认条件

<?php

namespace App\Repositories\Eloquent;

use App\Repositories\Transformers\ArticleTransformer;
use Prettus\Repository\Eloquent\BaseRepository;
use Prettus\Repository\Criteria\RequestCriteria;
use App\Repositories\Contracts\ArticleRepository;
use App\Models\Article;

/**
 * Class ArticleRepositoryEloquent
 * @package namespace App\Repositories\Eloquent;
 */
class ArticleRepositoryEloquent extends BaseRepository implements ArticleRepository
{
    /**
     * Specify Model class name
     *
     * @return string
     */
    public function model()
    {
        return Article::class;
    }


    public function transfomer()
    {
        return ArticleTransformer::class;
    }
    

    /**
     * Boot up the repository, pushing criteria
     */
    public function boot()
    {
        /**
         * RequestCriteria 是一个标准的 Criteria 实现。 它使筛选器能够根据请求中发送的参数在存储库中执行。
         * 您可以执行动态搜索,过滤数据和自定义查询。
         * 要在存储库中使用 Criteria,您可以在存储库的引导方法中添加新条件,或直接在控制器中使用,以便只过滤少数几个请求。
         */
        $this->pushCriteria(app(RequestCriteria::class));
    }
}

你也可以在 controller 中调用 setTransformer 方法来使用

$this->repository->setTransformer(new ArticleTransformer());

跳过存储库中定义的条件

当你在对 repository 使用了 transformer 之后,也许在某些场景下你不希望查询结果自动的被 transform 掉,你可以调用 repository 的 skipTransformer() 方法来跳过转换。

$this->repository->skipCriteria()->all();

使用 popCriteria 删除条件

$this->repository->popCriteria(new MyCriteria());

缓存

更改文件 config / repository.php 中的缓存设置

'cache' => [
     //启用或禁用缓存存储库
     'enabled' => true ,
    
     //缓存的生命周期
     'minutes' => 30 ,
    
     // Repository Cache,implementation Illuminate\Contracts\Cache\Repository
     'repository' => 'cache' ,
    
     //设置清除高速缓存
     'clean' => [
     //启用,禁用在更改时清除缓存
     'enabled' => true ,
    
     'on' => [
     //启用,在创建项目时禁用清除缓存
     'create' => true ,
    
     //启用,在升级项目时禁用清除缓存
     'update' => true ,
    
     //启用,在删除项目时禁用清除缓存
     'delete' => true ,
     ]]
     ],
     'params' => [
     //将用于绕过缓存存储库的请求参数
     'skipCache' => 'skipCache'
     ],
     'allowed' => [
     //仅允许对某些方法进行高速缓存
     'only' => null ,
    
     //允许缓存所有可用的方法,除了
     'except' => null
     ],
 ],

可以直接在存储库中覆盖这些设置

<?php

namespace App\Repositories\Eloquent;

use App\Repositories\Transformers\ArticleTransformer;
use Prettus\Repository\Eloquent\BaseRepository;
use Prettus\Repository\Criteria\RequestCriteria;
use App\Repositories\Contracts\ArticleRepository;
use App\Models\Article;
use Prettus\Repository\Traits\CacheableRepository;

/**
 * Class ArticleRepositoryEloquent
 * @package namespace App\Repositories\Eloquent;
 */
class ArticleRepositoryEloquent extends BaseRepository implements ArticleRepository
{
    use CacheableRepository;

    //设置缓存的生命周期到存储库
    protected $cacheMinutes = 90 ;

    // 可缓存的方法是:all,paginate,find,findByField,findWhere,getByCriteria
    protected $cacheOnly = ['all'];
    //或
    protected $cacheExcept = ['find'];
}

参考学习

ROR
laravel 学习-安装 entrust 和 l5-repository 2 个基本依赖
laravel 提供的简单强大的 repository