andersao/l5-repository实践记录

创建model

php artisan make:entity Article
 Would you like to create a Presenter? [y|N] (yes/no) [no]:
  y 
App\Transformers\ArticleTransformerPresenter created successfully.
 Would you like to create a Transformer? [y|N] (yes/no) [no]:
  y
Transformer created successfully.
 Would you like to create a Validator? [y|N] (yes/no) [no]:
  y
Validator created successfully.
 Would you like to create a Controller? [y|N] (yes/no) [no]:
 y
Request created successfully.
Request created successfully.
Controller created successfully.
Repository created successfully.
Bindings created successfully

生成或修改了以下文件

  • Model 模型文件
  • Presenters 常用于前端模板格式化输出 (可能不准确)

Presenters function as a wrapper and renderer for objects.

  • Transformer 用于model数据格式化输出
  • Validator 验证器
  • CreateRequest 创建数据请求
  • UpdateRequest 更新数据请求
  • Controller RESTfull控制器
  • Repository 资料库与资料库接口
 php artisan make:repository "Blog\Post"
 php artisan make:repository "Blog\Post" --fillable="title,content"
 php artisan make:entity Cat --fillable="title:string,content:text" --rules="title=>required|min:2, content=>sometimes|min:10"
  • Bindings 在Providers/RepositoryServiceProvider.php中注册
php artisan make:bindings Cats //可单独使用
$this->app->bind(\App\Repositories\ArticleRepository::class, \App\Repositories\ArticleRepositoryEloquent::class); 
  • 添加了对应的数据库迁移文件

添加模型字段 数据库迁移 测试数据填充

 $table->increments('id');
 $table->String('title',150)->comment('标题');
 $table->String('author',50)->comment('作者');
 $table->text('article')->comment('文章');
 $table->softDeletes()->comment('软删除');
 $table->timestamps();
  • 修改model文件添加字段
 protected $fillable = [
        'title',
        'author',
        'article'
    ];
  • 为了方便数据库的填充使用factories工厂文件与seeds种子文件

=>工厂文件

$factory->define(App\Entities\Article::class, function (Faker\Generator $faker) {

    return [
        'title' => $faker->sentence,
        'author'=> $faker->name,
        'article'=> $faker->text,
//        'img' => $faker->url,
//        'content' => $faker->text,
//        'sort' => $faker->randomDigit,
//        'pageviews' => $faker->randomDigit,
//        'tag' => $faker->randomDigit,
//        'status' => $faker->randomElement([-1, 0, 1]),
    ];
});

=>种子文件

//创建种子文件
artisan make:seeder ArticleTableSeeder
//修改种子文件
public function run()
    {
        $article = factory('App\Entities\Article',50)->create();
    }
//修改DatabasesSeeder
 public function run()
    {
         //$this->call(UsersTableSeeder::class);
        $this->call(ArticleTableSeeder::class);
    }

执行迁移与填充

php artisan  migrate 
php artisan  db:seed
//或者直接使用下面的
php artisan migrate:refresh --seed

注册服务 添加路由 尝试输出

  • 注册服务
//在AppServiceProvider的register中添加 
$this->app->register(RepositoryServiceProvider::class);
  • 添加路由
//在路由文件中添加 
Route::resource('article', ArticlesController::class);
  • 修改控制器并访问地址
public function index()
    {
        $this->repository->pushCriteria(app('Prettus\Repository\Criteria\RequestCriteria'));
        $articles = $this->repository->all();

        if (request()->wantsJson()) {

            return response()->json([
                'data' => $articles,
            ]);
        }

        dd($articles);
        return $articles->toJSON();
//        return view('articles.index', compact('articles'));
    }

访问 http://192.168.10.10:90/article
正常返回json格式数据

简单的搜索功能实现

  • 在ArticleRepositoryEloquent中添加允许搜索字段
//格式  字段=>搜索方式  默认搜索方式为 =
protected $fieldSearchable = [
        'id'=>'=',
        'title'=>'like',
        'author'
    ];
select * from `articles` where (`articles`.`id` = 'Ratione' or `articles`.`title` like '%Ratione%' or `articles`.`author` = 'Ratione') and (`articles`.`id` = 'Ratione' or `articles`.`title` like '%Ratione%' or `articles`.`author` = 'Ratione')


http://192.168.10.10:90/article?search=Ratione&searchFields=title:like

select * from `articles` where (`articles`.`title` like '%Ratione%') and (`articles`.`title` like '%Ratione%')


http://192.168.10.10:90/article?search=id:15;title:Ratione&searchFields=title:like;id:=

select * from `articles` where (`articles`.`id` = '15' or `articles`.`title` like '%Ratione%') and (`articles`.`id` = '15' or `articles`.`title` like '%Ratione%')

正常返回json格式数据

过滤功能的实现

select `id`, `author` from `articles`


http://192.168.10.10:90/article?filter=id;author&orderBy=id&sortedBy=desc

select `id`, `author` from `articles` order by `id` desc, `id` desc

关联查询功能实现

  • TODO

普通的删除添加与修改功能的实现

  • 为了方便测试可以关闭csrf验证并修改updateRepository与createRepository中的用户权限验证

1.注释掉http/Kernel.php中的

\App\Http\Middleware\VerifyCsrfToken::class

2.修改updateRepository与createRepository中的authorize()

public function authorize()
    {
        return true;
    }
namespace App\Entities;
use Illuminate\Database\Eloquent\Model;
use Prettus\Repository\Contracts\Transformable;
use Prettus\Repository\Traits\TransformableTrait;
use Illuminate\Database\Eloquent\SoftDeletes;
class Article extends Model implements Transformable
{
    use TransformableTrait;
    use SoftDeletes;
    protected $fillable = [
        'title',
        'author',
        'article'
    ];
}

使用postman用delete方法访问http://192.168.10.10:90/article/7
数据库中文章并没有被直接删除,而且搜索与访问均失败
软删除后如果想要强制删除可在控制器中添加,或者在资料库与资料库接口中扩展

public function forceDestroy($id)
    {
        $deleted = $this->repository->find($id)->forceDelete();

        if (request()->wantsJson()) {

            return response()->json([
                'message' => 'Article forceDelete.',
                'deleted' => $deleted,
            ]);
        }

        return redirect()->back()->with('message', 'Article forceDelete.');
    }

数据库中文章被删除

缓存的使用

  • 这里需要在repository中添加缓存trait
use Prettus\Repository\Contracts\CacheableInterface;
use Prettus\Repository\Traits\CacheableRepository;
class ArticleRepositoryEloquent extends BaseRepository implements ArticleRepository
{
    /**
     * 开启缓存
     *
     */
use CacheableRepository;
......
}
//为了方便,修改redis配置文件,使其可以后台运行,并可以远程连接
//关于远程连接bind
//这里很多人会误以为绑定的ip应该是请求来源的ip。其实不然,这里应该绑定的是你redis服务器本身接受请求的ip。http://www.2cto.com/database/201507/419799.html
redis-server ./redis.conf

然后修改.env文件,如果之前使用过file缓存更换为redis后,redis无法使用,则说明laravel配置被缓存了,需要删除该缓存

artisan config:clear
artisan cache:clear
  • 可以发现如果重复上述查找,修改,删除,添加测试,数据库并不会每次都会进行查询,而且通过RedisDesktopManager可以清楚的看见会有对象缓存进去。
  • 进行不同条件的检索时会有不同的对象缓存进redis,所以如果不是相同条件进行检索,还是会对数据库进行操作
  • 在任何的修改,删除(包括软删除),添加后,redis缓存都会被清除
  • 并发性能测试
    安装siege后进行测试,执行命令
siege -c 255 -r 1 http://192.168.10.10:90/article 

不使用缓存时

vagrant@homestead:/usr/local/etc$ ../siege/src/siege -c 255 -r 1 http://192.168.10.10:90/article
** SIEGE 4.0.3rc3
** Preparing 255 concurrent users for battle.
The server is now under siege...
Transactions:                    255 hits
Availability:                 100.00 %
Elapsed time:                  39.52 secs
Data transferred:               5.50 MB
Response time:                 18.80 secs
Transaction rate:               6.45 trans/sec
Throughput:                     0.14 MB/sec
Concurrency:                  121.30
Successful transactions:         255
Failed transactions:               0
Longest transaction:           39.45
Shortest transaction:           1.44

使用缓存时

vagrant@homestead:/usr/local/etc$ ../siege/src/siege -c 255 -r 1 http://192.168.10.10:90/article
** SIEGE 4.0.3rc3
** Preparing 255 concurrent users for battle.
The server is now under siege...
Transactions:                    255 hits
Availability:                 100.00 %
Elapsed time:                  52.13 secs
Data transferred:               5.33 MB
Response time:                 34.30 secs
Transaction rate:               4.89 trans/sec
Throughput:                     0.10 MB/sec
Concurrency:                  167.77
Successful transactions:         255
Failed transactions:               0
Longest transaction:           52.08
Shortest transaction:          16.37

结果让我有点吃惊。。。开了比没开居然还稍微差点,关闭调试模式也一样。不知道是我电脑性能不行还是因为查询结构太简单导致的。。。。。。也可能是其他地方没有使用redis比如session之类

TODO

过滤器

  • 可以修改Validator文件,也可以分别修改Create与Update的Request文件。其中Request优先级高于Validator,而且Validator文件中无法正常添加使用自定义错误信息,原因可能是Valitdator插件对应版本为laravel4,作者已经不再维护了。。。。。不过可以尝试使用这个方法https://github.com/andersao/laravel-validator/issues/21
    Validator中
protected $rules = [
        ValidatorInterface::RULE_CREATE => [
            'title' => 'required|max:50',
            'text'  => 'min:3',
            'author'=> 'required|max:8'

        ],
        ValidatorInterface::RULE_UPDATE => [
            'title' => 'required',

        ],
   ];
//  错误信息不能正常调出。
//    protected $messages= [
//            'title.required' => 'attt.',
//            'min' => 'minnn.',
//            'author.max' => 'maxxxx.',
//    ];
//    public function messages()
//    {
//        return $this->messages;
//    }

CreateRequest中

public function rules()
    {
        return [
            'title' => 'required|max:15',
            'text'  => 'min:6',
            'author'=> 'required|max:7'
        ];
    }

    public function messages()
    {
        return [

            'title.required' => '请填写标题.',
            'min' => '低于最小字数.',
            'author.max' => '超过字数限制.',

        ];
    }

格式化输出

  • 顾名思义他只控制输出格式,因此即便是只输出部分字段,他还是会从数据库中选择所有字段。通过修改Transform文件然后在仓库中或者控制器中注册Presenter,即可格式化输出。默认为json格式输出。
    修改Transform文件如下后,访问
public function transform(Article $model)
    {
        return [
            'id'         => (int) $model->id,

            /* place your other model properties here */
            '标题' =>$model->title,
            '作者' =>$model->author,
            'article' =>$model->article,

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

修改仓库

public function presenter()
    {
        return "App\\Presenters\\ArticlePresenter";
    }

或者修改控制器

public function __construct(ArticleRepository $repository, ArticleValidator $validator)
    {
        $this->repository = $repository;
        $this->repository->setPresenter("App\\Presenters\\ArticlePresenter");
        $this->validator  = $validator;
    }
  • 当然也可以通过修改Model文件来格式化输出。但优先级比Transform文件低。
    Model文件
namespace App\Entities;
use Illuminate\Database\Eloquent\Model;
use Prettus\Repository\Contracts\Transformable;
use Prettus\Repository\Traits\TransformableTrait;
use Illuminate\Database\Eloquent\SoftDeletes;
use Prettus\Repository\Traits\PresentableTrait;
class Article extends Model implements Transformable
{
    use TransformableTrait;
    use SoftDeletes;
    use PresentableTrait;
    protected $fillable = [
        'title',
        'author',
        'article'
    ];
    public function transform()
    {
        return [
            'id'         => (int) $this->id,
            /* place your other model properties here */
            '标题' =>$this->title,
            '作者' =>$this->author,
            '文章' =>$this->article,
            'created_at' => $this->created_at,
            'updated_at' => $model->updated_at
        ];
    }
}

控制器

public function __construct(ArticleRepository $repository, ArticleValidator $validator)
    {
        $this->repository = $repository;
        //$this->repository->setPresenter("App\\Presenters\\ArticlePresenter");
        $this->repository->setPresenter("Prettus\\Repository\\Presenter\\ModelFractalPresenter");
        $this->validator  = $validator;
    }

或者修改仓库

public function presenter()
    {
        return "Prettus\\Repository\\Presenter\\ModelFractalPresenter";
    }
  • 当然也可以跳过该自定义格式或者只在部分地方使用
public function show($id)
    {
//部分函数内跳过
        $this->repository->skipPresenter();
//在部分函数内使用
        $this->repository->setPresenter("App\\Presenters\\ArticlePresenter");
        $article = $this->repository->find($id);

        if (request()->wantsJson()) {

            return response()->json([
                'data' => $article,
            ]);
        }
//        return $article->toJSON();
        return $article;
//        return view('articles.show', compact('article'));
    }

转载请注明出处,谢谢=.=

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 195,898评论 5 462
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 82,401评论 2 373
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 143,058评论 0 325
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,539评论 1 267
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,382评论 5 358
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,319评论 1 273
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,706评论 3 386
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,370评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,664评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,715评论 2 312
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,476评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,326评论 3 313
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,730评论 3 299
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,003评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,275评论 1 251
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,683评论 2 342
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,877评论 2 335

推荐阅读更多精彩内容