推荐:好用的 Laravel Repository 包

什么是Repository模式,如何使用Repository模式

这里就不再啰嗦了,请参见以下几个链接
如何使用 Repository 模式?
关于 Repository 的设计模式
laravel-china.org搜索

我的使用历程

原由

MVC在如今仍然是流行趋势,但多数框架都只提供基础的MVC架构。
几年前在开发中我们经常会遇到问题Model过于臃肿,写着写着就会变成类似于万能类,最后面的人就真成了接盘侠了。
很不幸我就是其中之一。后来我就一直在思考如何才能让Model看起来清爽,功能更加单一简洁。(当时并不知道Repository),终于开始重构。一把心酸泪。。。。。最多的是组合和Trait

使用Laravel

最开始接触Laravel就是感觉它的文档清爽,以为是个简单的框架,结果不小心一入坑,才发现被它的外表给欺骗了。
但却也为此深深爱上了它,是啊,这不就是我一直追求的吗?无限的灵活性,可替换,越研究代码越发现处处都是精髓。
但在Laravel中也不可避免的基础MVC模式,上述问题仍然存在。

初期使用

一直以为我都遵循一个核心:以仓库层为处理数据基础,为SerivceController等提供数据供给,仓库需要的原始数据则通过Model中获取。这样可以完全分离ModelController的依赖。
最开始在Laravel中使用是通过定义大量的RepositoryInterface来注入,bind,实现具体的Repository工作类。
这是理想的使用方法可替换性很强。

遇到的问题

  • 实际开发过程中Repository基本不会被替换,无数的Interface带来的规范,也带来了开发的麻烦。
  • 在使用Repository模式中我们不断的注入Model,每个方法都需要直接Model来进行一次次的查询数据集,却失去了在外层链式调用的便捷性(这其实并不合理,但存在即有原由)。

中间的折中

后来索性在开发中我们去掉了Interface的约束,直接作用功能类来注入使用,此时简洁性和便捷性大大的提高,如果非要替换仍然bind可以解决问题。这样的开始一直持续很长时间。但是像链接调用仍然没有解决,为些我们开发出了新的仓库包。https://github.com/crcms/repository

再次轮回

开始玩微服务,开始分离代码,当然就离不开RPC,十分庆幸我们使用了Repository模式,通过开启对应的Rpc Repository,我们可以很快进行本地Repository切换,以Interface来约束。

便捷的Repository包

基础示例

class TestRepository extends AbstractRepository
{
    /**
     * @var array
     */
    protected $guard = [
        'id', 'title','other'
    ];

    /**
     * @return TestModel
     */
    public function newModel(): TestModel
    {
        return app(TestModel::class);
    }

    /**
     * @param int $perPage
     * @return LengthAwarePaginator
     */
    public function paginate(AbstractMagic $magic = null, int $perPage = 15): LengthAwarePaginator
    {
        $query = $this->where('built_in', 1);

        if ($magic) {
            $query->magic($magic);
        }

        return $query->orderBy($this->getModel()->getKeyName(), 'desc')->paginate($perPage);
    }

    /**
     * @param int $name
     * @param int $title
     */
    public function updateName(string $name, string $title)
    {
        $this->getModel()->where('name', $name)->update(['title' => $title]);
    }

}

超好用的Magic方法

在多条件搜索中,肯定会存在大量的判断,优雅度太低,如:

if($request->input('username')) {
    $query->where('username',$username)
}

if($request->input('email')) {
    $query->where('email',$email)
}

.......

但通过QueryMagic方法我们可以轻松优雅解决这些问题,示例:

创建Magic

use CrCms\Repository\AbstractMagic;
use CrCms\Repository\Contracts\QueryRelate;

class TestMagic extends AbstractMagic
{
    /**
     * @param QueryRelate $queryRelate
     * @param int $id
     * @return QueryRelate
     */
    protected function byName(QueryRelate $queryRelate, string $name)
    {
        return $queryRelate->where('name', $name);
    }

    /**
     * @param QueryRelate $queryRelate
     * @param string $title
     * @return QueryRelate
     */
    protected function byTitle(QueryRelate $queryRelate, string $title)
    {
        return $queryRelate->where('title', 'like', "%{$title}%");
    }

    /**
     * @param QueryRelate $queryRelate
     * @param int $id
     * @return QueryRelate
     */
    protected function byId(QueryRelate $queryRelate, int $id)
    {
        return $queryRelate->where('id', $id);
    }
}

使用Magic(这里只是简单示例):

    public function paginate(array $condition, int $perPage = 15): LengthAwarePaginator
    {
        return $query->magic(new TestMagic($condition))->orderBy($this->getModel()->getKeyName(), 'desc')->paginate($perPage);
    }

更多

开发此包的原因是在这之前我并示找到我想要的(适合我的)兼具Model的灵活性以及数据仓库的分离模式,所以为此开发了这个仓库包。目前此包已经使用在好几个项目中目前运行良好。
后面还打算兼容TP以及Yii等使用率高的框架,暂时只支持Laravel
更多详情,请移步github:https://github.com/crcms/repository

最后

哈哈,请原谅我着急的文本描述,希望对需要的人以及面临和我曾经一样困惑的人有所帮助。
原文出处:crcms-blog

本作品采用《CC 协议》,转载必须注明作者和本文链接
本帖由系统于 3年前 自动加精
《L02 从零构建论坛系统》
以构建论坛项目 LaraBBS 为线索,展开对 Laravel 框架的全面学习。应用程序架构思路贴近 Laravel 框架的设计哲学。
《L03 构架 API 服务器》
你将学到如 RESTFul 设计风格、PostMan 的使用、OAuth 流程,JWT 概念及使用 和 API 开发相关的进阶知识。
讨论数量: 10

我一直没搞明白 数据库的逻辑为什么要写在model里面呢 我一直是model里面只写主键定义 表名 可批量修改名单 以及模型关联关系 除此之外我没有其他的逻辑了 我是不是写错了啊 求指点

3年前 评论

@pigsney 这些没有严格意义上的对与错吧,我的Model也只有这些东西,只是看功能分类,如何设计吧。

我曾经看到过一个人一个Controller 近 5000行代码,当时他还对我说,精通OOP。。。。。。

基本上我现在的处理逻辑是基于MVC再次多加处理层而已,比如我的Service才是正真严格意义上的逻辑处理,Repository:数据供给器,Model相关关系定义,Action通用动作行为定义
个人觉得你这样写Model没问题!

3年前 评论

啥都不说,先点赞再看;楼主还是把文档丰富下好点,比较好查阅。 :+1:

3年前 评论

@ma1232006 多谢支持,更加完善的文档会有的!

3年前 评论
ALMAS

可不可以分享一些用 Laravel 开发微服务方面的经验、技巧?

3年前 评论

@pigsney 查询也不写在里面吗?

3年前 评论

@ALMAS 目前我们也是在探索开发阶段,没有相关经验不敢妄谈,等踩过坑了可以分享。主要的是开发思路是Docker+Swoole+Laravel+DB+Redis,中间通信使用Swoole的TCP通信或者Http通信,中间增加连接池熔断等。。。

3年前 评论
ThinkCsly

:pensive:

3年前 评论

个人觉得在laravel用仓库的地方很少的,重复代码就自己写个仓库类,然后依赖注入就好,不会很多,没必要加扩展

3年前 评论

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!