Repository 2.x 设计模式
👋🏼 您当前浏览的文档为 2.x
写在前面
TIP
需要为 Repository
绑定 interface
,Repository
服务提供
需要在服务容器AppServiceProvider
类 register()
中绑定 Repository
$this->app->bind(IManage::class, ManageRepo::class);//管理员
建议新建一个服务类 RepositoryServiceProvider
用于专门管理Repository
服务的绑定。保持整个编码风格的整洁。 甚至可以再按业务模块去区分provider
,然后在主服务类中引入各业务模块的provider
。
创建一个新的provider
和按业务拆分独立的provider
的原因是:当项目越来越大的时候,绑定服务结构会变得非常凌乱。 设想下:每个模型都有自己的Repository
,那么项目中的AppServiceProvider
和RepositoryServiceProvider
可读性将会大大降低。
服务提供者
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 命令生成的文件,会根据具体类型更改文件名:PostModel
、IPost
、PostRepo
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());
}
}