Skip to content

Repository 2.x 设计模式

👋🏼 您当前浏览的文档为 2.x

写在前面

TIP

需要为 Repository 绑定 interface,Repository服务提供

需要在服务容器AppServiceProviderregister() 中绑定 Repository

$this->app->bind(IManage::class, ManageRepo::class);//管理员

建议新建一个服务类 RepositoryServiceProvider 用于专门管理Repository服务的绑定。保持整个编码风格的整洁。 甚至可以再按业务模块去区分provider,然后在主服务类中引入各业务模块的provider

创建一个新的provider和按业务拆分独立的provider的原因是:当项目越来越大的时候,绑定服务结构会变得非常凌乱。 设想下:每个模型都有自己的Repository,那么项目中的AppServiceProviderRepositoryServiceProvider可读性将会大大降低。

服务提供者

php artisan make:provider RepositoryServiceProvider

注册服务提供者

服务提供者都是通过配置文件 config/app.php 进行注册,只需要将服务添加到 providers数组中


'providers' => [
    // 其他服务提供者
    App\Providers\RepositoryServiceProvider::class,
]

使用

创建 Model

一定要设置 $fillable

namespace App;

class PostModel extends Model { 

    protected $fillable = [
        'title',
        'author',
        ...
     ];

     ...
}

创建 Repository


namespace App;

use JoyceZ\LaravelLib\Repositories\BaseRepository;
use App\Services\Repositories\Blog\Interfaces\IPost;

class PostRepo extends BaseRepository implements IPost {

    /**
     * Specify Model class name
     *
     * @return string
     */
    function model()
    {
        return "App\\PostModel";
    }
}

Artisan 命令生成

根目录配置,参见Config 配置文件

config配置

...
'generator' => [//Artisan 命令生成 Repository 和 enum 相关文件的指定根目录
    'basePath' => app()->path(),
    'rootNamespace' => 'App\\',
    'paths' => [
        'models' => 'Services\\Models',//model 生成根目录
        'repositories' => 'Services\\Repositories',//repository 生成根目录
        'interfaces' => 'Services\\Repositories',//repository interfaces 生成根目录。实际在生成中会转成 'App\Services\Repositories\Bolg\Interfaces\IPost.php
        'enums' => 'Services\\Enums',
    ]
]

Commands

提示

Artisan 命令生成的文件,会根据具体类型更改文件名:PostModelIPostPostRepo

php artisan make:repository "Blog\Post"

执行以上命名会生成三个对应的文件如下

  • App\Services\Models\Bolg\PostModel.php
  • App\Services\Repositories\Bolg\Interfaces\IPost.php
  • App\Services\Repositories\Bolg\PostRepo.php

方法

RepositoryInterface

/**
 * 获取当前的model对象
 * @return Model
 */
public function getModel(): Model;

/**
 * 根据主键查询
 * @param $id
 * @param array $columns
 * @return mixed
 */
public function find($id, $columns = ['*']);

/**
 * 按字段值查询单条数据
 * @param $field
 * @param null $value
 * @param array $columns
 * @return mixed
 */
public function findByField($field, $value = null, $columns = ['*']);

/**
 * 按字段值查询列表
 * @param $field
 * @param null $value
 * @param array $columns
 * @return mixed
 */
public function findAllByField($field, $value = null, $columns = ['*']);

/**
 * 根据查询条件获取数据
 * @param array $where
 * @param array $columns
 * @return mixed
 */
public function findWhere(array $where, $columns = ['*']);

/**
 * 根据字段多个值获取数据列表
 * @param string $field
 * @param array $values
 * @param array $columns
 * @return mixed
 */
public function findWhereIn(string $field, array $values, $columns = ['*']);

/**
 * 查询不在指定字段值中的数据
 * @param string $field
 * @param array $values
 * @param array $columns
 * @return mixed
 */
public function findWhereNotIn(string $field, array $values, $columns = ['*']);

/**
 * 判断数据是否存在,存在返回true 不存在返回false
 * @param array $where 查询条件
 * @return bool
 */
public function existsWhere(array $where): bool;

/**
 * 判断数据是否存在,存在返回 false 不存在返回 true
 * @param array $where
 * @return bool
 */
public function doesntExistWhere(array $where): bool;

/**
 * 根据主键id获取单条数据
 * @param int $id 主键id
 * @return mixed
 */
public function getByPkId(int $id);

/**
 * 根据条件,获取一条指定字段数据
 * @param array $columns 查询字段
 * @return mixed
 */
public function first(array $columns = ['*']);

/**
 * 查找第一条数据,获取创建
 * @param array $attributes
 * @return mixed
 */
public function firstOrCreate(array $attributes = []);

/**
 * 没有查找到数据,抛出异常
 * @param array $condition
 * @return mixed
 */
public function firstOrFail(array $condition);

/**
 * 根据条件,获取全部数据
 * @param array $columns 要查询的字段
 * @return mixed
 */
public function all(array $columns = ['*']);

/**
 * 联动查询条件,
 * @param $where
 * @return $this
 */
public function where($where);

/**
 * 设置查询数量
 * @param int $limit
 * @return $this|mixed
 */
public function limit(int $limit);

/**
 * 设置要查询的字段
 * @param array ...$values
 * @return mixed
 */
public function select($values);

/**
 * 排序
 * @param $column
 * @param string $direction
 * @return mixed
 */
public function orderBy($column, $direction = 'asc');

/**
 * 获取分页
 * @param array $columns
 * @param int $limit
 * @return mixed
 */
public function paginate($columns = ['*'], $limit = 0);

/**
 * 创建一条数据,不联表状态
 * @param array $attributes
 * @return mixed
 */
public function create(array $attributes);

/**
 * 批量插入
 * @param array $attributes
 * @return mixed
 */
public function createBatch(array $attributes);

/**
 * 根据主键id,更新一条数据
 * @param array $attributes 要更新的字段
 * @param int $id 更新主键值
 * @return mixed
 */
public function updateById(array $attributes, int $id);

/**
 * 根据指定条件更新数据,批量更新
 * @param array $condition 更新条件
 * @param array $attributes 要更新的字段
 * @return mixed
 */
public function updateByWhere(array $condition, array $attributes);

/**
 * 删除单条数据
 * @param int $id 主键值
 * @return int
 */
public function deleteById(int $id);

/**
 * 根据id批量删除
 * @param array $ids
 * @return mixed
 */
public function deleteByIds(array $ids);

/**
 * 根据主键,更新某个字段,模型要指定主键名
 * @param int $id 主键id值
 * @param string $filedName 字段名称
 * @param string $fieldValue 字段值
 * @return mixed
 */
public function updateFieldById(int $id, string $filedName, string $fieldValue);

/**
 * 统计数量
 *
 * 注意:
 *     1.不建议使用 $columns='*',请指定特定字段名,如果没指定,默认为主键字段名
 *     2.不建议用 count() 来判断数据存不存在,请使用find 或者 first 来判断数据是否存在
 *
 * @param array $condition 查询条件
 * @param string $columns 统计字段
 * @return int
 */
public function count(array $condition = [], string $columns = ''): int;

/**
 * 求和
 * @param array $condition
 * @param string $columns
 * @return mixed
 */
public function sum(array $condition = [], string $columns = '');

/**
 * 求平均值
 * @param array $condition
 * @param string $columns
 * @return mixed
 */
public function avg(array $condition = [], string $columns = '');

/**
 * 求最大值
 * @param array $condition
 * @param string $columns
 * @return mixed
 */
public function max(array $condition = [], string $columns = '');

/**
 * 求最小值
 * @param array $condition
 * @param string $columns
 * @return mixed
 */
public function min(array $condition = [], string $columns = '');

/**
 * 指定某个字段值自增
 * @param array $condition
 * @param string $filedName
 * @param int $amount
 * @return mixed
 */
public function increment(array $condition, string $filedName, int $amount = 1);

/**
 * 指定某个字段递减
 * @param array $condition
 * @param string $filedName
 * @param int $amount
 * @return mixed
 */
public function decrement(array $condition, string $filedName, int $amount = 1);

/**
 * 解析一条业务数据
 * @param array $row
 * @return array
 */
public function parseDataRow(array $row): array;

/**
 * 解析多条业务数据格式,循环调用 parseDataRow 方法,只需要在具体的业务逻辑继承重写 parseDataRow 方法即可
 * @param array $rows
 * @return array
 */
public function parseDataRows(array $rows): array;

/**
 * 得到某个列的数组
 * 使用场景:以 key 为数组索引,获取指定字段。或者直接获取一个字段得一维数组,比如:[1001,1002,1003] (只获取uid) 字段
 * @param string $column 字段名 多个字段用逗号分隔
 * @param array $condition 查询条件
 * @param string $key 指定索引名
 * @return array
 */
public function column(string $column, $condition = [], string $key = ''): array;

/**
 * 批量更新多条数据,默认更新主键为id,若不是,就以数组第一个主键为key进行更熟数据
 * @param array $multipleData 二维数据
 * @return bool
 */
public function updateBatch(array $multipleData = []): bool;

/**
 * 更新或者创建
 * @param array $attributes
 * @param array $values
 * @return mixed
 */
public function updateOrCreate(array $attributes, array $values = []);

/**
 * 根据条件批量删除数据
 * @param array $condition
 * @return mixed
 */
public function deleteWhere(array $condition);

/**
 * @param array $relations
 * @return $this
 */
public function with(array $relations);

/**
 * 关联模型计数
 * @param array $relations
 * @return mixed
 */
public function withCount(array $relations);

/**
 * 同步关联
 * @param $id
 * @param $relation
 * @param $attributes
 * @param bool $detaching
 * @return mixed
 */
public function sync($id, $relation, $attributes, $detaching = true);

/**
 * 执行事务
 * 传入匿名函数就是自动,不传入就是手动
 * @param callable|null $callable
 * @return mixed
 */
public function transaction(callable $callable = null);

/**
 * 事务回滚
 * @return mixed
 */
public function rollBack();

/**
 * 提交事务
 * @return mixed
 */
public function commit();

/**
 * 打印sql语句
 * @param \Closure $callback
 * @param string $tableName 数据库名
 * @return mixed
 */
public function getQuerySql(Closure $callback, string $tableName = '');

查询构造器

/**
 * 联动查询条件,
 * @param $where
 * @return $this
 */
public function where($where);

/**
 * 设置查询数量
 * @param int $limit
 * @return $this|mixed
 */
public function limit(int $limit);

/**
 * 设置要查询的字段
 * @param array ...$values
 * @return mixed
 */
public function select($values);

/**
 * 排序
 * @param $column
 * @param string $direction
 * @return mixed
 */
public function orderBy($column, $direction = 'asc');

内置查询条件


/**
 * 将 where 查询条件,追加到模型
 */
protected function applyConditions(array $where);

字段条件

[operator] 代表数据库支持数据库任意操作符

操作符对应

$this->model->whereIn($field, $val);//IN
$this->model->whereNotIn($field, $val);//NOTIN
$this->model->whereExists($val);//NOTIN
$this->model->whereDate($field, $operator, $val);//`DATE`、`DATE [operator]`
$this->model->whereDay($field, $operator, $val);//`DAY`、`DAY [operator]`
$this->model->whereMonth($field, $operator, $val);//`MONTH`、`MONTH [operator]`
$this->model->whereYear($field, $operator, $val);//`YEAR`、`YEAR [operator]`
$this->model->whereTime($field, $operator, $val);//`TIME`、`TIME [operator]`
$this->model->whereHas($field, $val);//HAS
$this->model->whereHasMorph($field, $val);//HASMORPH
$this->model->whereDoesntHave($field, $val);//DOESNTHAVE
$this->model->whereDoesntHaveMorph($field, $val);//DOESNTHAVEMORPH
$this->model->whereBetween($field, $val);//BETWEEN
$this->model->whereBetweenColumns($field, $val);//BETWEENCOLUMNS
$this->model->whereNotBetween($field, $val);//NOTBETWEEN
$this->model->whereNotBetweenColumns($field, $val);//NOTBETWEENCOLUMNS
$this->model->whereRaw($val);//RAW

使用

$posts = $this->repository->findWhere([
    //Default Condition =
    'state_id'=>'10',
    'country_id'=>'15',

    //Custom Condition
    ['columnName1','>','10'],

    //DATE, DAY, MONTH, YEAR
    ['columnName2','DATE','2021-07-02'], //whereDate
    ['columnName3','DATE >=','2021-07-02'], //whereDate with operator

    ['columnName4','IN',['value1','value2']], //whereIn
    ['columnName5','NOTIN',['value1','value2']], //whereNotIn
    ['columnName6','EXIST',''], //whereExists
    
    //HAS, HASMORPH, DOESNTHAVE, DOESNTHAVEMORPH
    ['columnName7','HAS',function($query){}], //whereHas

    //BETWEEN, BETWEENCOLUMNS, NOTBETWEEN, NOTBETWEENCOLUMNS
    ['columnName8','BETWEEN',[10, 100]], //whereBetween
]);

写在后面

为了不过重设计,我们在编写业务Repository时,可无需单独编写一个Interface来实现Repository接口。

同时也无需编写provider进行服务注册

Repository 类

namespace App\Services\Repositories\Student;


use App\Services\Models\Student\StudentModel;
use JoyceZ\LaravelLib\Repositories\BaseRepository;

class StudentRepo extends BaseRepository
{
    /**
     * Specify Model class name
     *
     * @return string
     */
    function model()
    {
        return StudentModel::class;//"App\\Post";
    }
}

Controller 类


namespace App\Http\Controllers\Home;


use App\Http\Controllers\Controller;
use App\Services\Repositories\Student\StudentRepo;

class Index extends Controller
{


    public function index(StudentRepo $studentRepo)
    {

        dd($studentTestRepo->getStudentByTeacher());
    }
}

根据 MIT 许可证发布。