an architecture for laravel
qq:680531281
项目架构分层,代码生成器,快速进入开发阶段,拆分职责降低耦合。
执行以下命令获取包的最新版本:
composer require phpno1/architecture
php artisan vendor:publish --provider "Phpno1\Architecture\Providers\ArchitectureServiceProvider"
说明:用命令生成仓储文件时(phpno1:entity || phpno1:repository),会自动生成ArchitectureServiceProvider文件。
# 在config/app.php中
'providers' => [
// ......
App\Providers\ArchitectureServiceProvider::class,
];
//architecture.php
'pagination' => [//默认分页数量
'limit' => 20
],
'cache' => [//缓存时间
'enabled' => true,
'minutes' => 10,
],
'order' => [//排序字段
'o',
],
'generator' => [//代码生成器命名空间
'root_namespace' => 'App\\',
'namespace' => [
'controller' => 'Backend',
'repository_eloquent' => 'Repository\\Eloquent',
'repository' => 'Repository\\Contracts',
'criteria' => 'Architecture\\Criterias',
'provider' => 'Providers\\ArchitectureServiceProvider',
'service' => 'Services',
'model' => 'Models',
'response' => 'Http\\Responses',
'filter' => 'Repository\\Filters'
]
]
说明:使用命令创建仓储文件时(phpno1:entity和phpno1:repository),会自动绑定接口与实现类关系。
//@params {name} 生成文件名称
//@params {--resource} 生成资源方法(参照laravel控制器 资源控制器)
php artisan phpno1:entity {name} {--resource}
//@params {name} 控制器名称
//@params {--resource} 生成资源方法(参照laravel控制器 资源控制器)
php artisan phpno1:controller {name} {--resource}
@params {name} 文件名称
@params {--resource} 生成资源方法
php artisan phpno1:service {name} {--resource}
@params {name} 限制类名称
php artisan phpno1:criteria {name}
@params {name} 过滤类名称
@params {--prefix=} 命名空间
@params {--sort} 排序方法
php artisan phpno1:filter {name} {--prefix=} {--sort}
@params {name} 模型名称
php artisan phpno1:model {name}
php artisan phpno1:provider
@params {name} 仓库名称
php artisan phpno1:repository {name}
@params {name} 文件名称
@params {--dir=} 生成目录
php artisan phpno1:request {name} {--dir=}
@params {name} 文件名称
@params {--dir=} 生成目录
php artisan phpno1:response {name} {--dir=}
@params {name} 文件名称
php artisan phpno1:seeder {name}
php artisan phpno1:entity User --resource
生成文件 (注:以下命令生成文件路径可以通过配置修改architecture.php)
<?php
namespace App\Http\Controllers\Backend;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
use App\Services\UserService;
use App\Http\Responses\User\IndexResponse;
class UserController extends Controller
{
private $user;
public function __construct(UserService $userService)
{
$this->user=$userService;
}
/**
* Display a listing of the resource.
*
* @return \Illuminate\Http\Response
*/
public function index()
{
//
$result=$this->user->getUsers();//这里调用是业务层资源方法
return new IndexResponse($result);
}
<?php
namespace App\Http\Responses\User;
use Illuminate\Contracts\Support\Responsable;
use App\Traits\ResponseTrait;
class UserIndexResponse implements Responsable
{
use ResponseTrait;
protected $result;
public function __construct($result)
{
$this->result = $result;
}
public function toResponse($request)
{
$data = $this->transform();
return $data;
}
protected function transform()
{
//分页数据例子
$this->result->getCollection()->transform(function ($user) {
return [
'id' => $user->id,
'name' => $user->name,
];
});
//集合数据例子
$this->result->transform(function ($user) {
return [
'id' => $user->id,
'name' => $user->name,
];
});
return $this->result;
}
}
// 获取所有记录
$this->repository->all();
// 根据id查询单条记录
$this->repository->find(int $id);
// 获取第一条记录
$this->repository->first();
// 获取总记录数
$this->repository->count();
// 根据一个或多个 AND WHERE 条件查询。得到一个结果集
// 单个条件写法:->findWhere('name', 'tome');
// 多个条件写法:->findWhere(['name', 'tome'], ['age', '>', 20]);
$this->repository->findWhere(...$condition);
// 根据一个或多个 AND WHERE 条件查询。得到一条记录。
$this->repository->findWhereFirst(...$condition);
// 根据一个或多个 AND WHERE 条件获取记录数
$this->repository->findWhereCount(...$condition);
// 获取分页数据
$this->repository->paginate(int $perPage = 10);
// 插入记录
$this->repository->create(array $properties);
// 修改记录
$this->repository->update(int $id, array $properties);
// 根据id删除
$this->repository->delete(int $id);
// 用于加载预设的自定义标准操作 (Criterias目录中的类),后面会详细介绍
$this->repository->withCriteria(...$criteria);
// 把Repository转换成Model或者Build对象,后续可以使用框架提供的ORM操作
$this->repository->toEntity();
// 把Build对象转回Repository对象
$this->repository->toRepository(Builder $entity);
//请重写boot方法 不要重写构造方法
function boot()
{
}
namespace App\Repositories\Criterias;
class ByCreateTime implements ICriteria
{
public function apply($entity)
{
return $entity->latest();
}
}
public function getUserListByCreateTime()
{
return $this->repository
->withCriteria(
new ByCreateTime()
// more...
)->paginate();
}
class UserRepositoryEloquent extends AbstractRepository implements UserRepository
{
// 设置过滤映射
protected $filters = [
'email' => EmailFilter::class,
'name' => NameFilter::class,
];
public function entity()
{
return User::class;
}
// 过滤和排序在withCriteria中添加过滤和排序操作类FilterRequest
public function findUserListByPage()
{
return $this->withCriteria(
new FilterRequest($this->filters)
)->paginate();
}
// something...
}
namespace App\Repositories\Filters\User;
use App\Repositories\Filters\AbstractFilter;
class NameFilter extends AbstractFilter
{
// 过滤操作
public function filter($entity, $value)
{
return $entity->where('name', $value);
}
}
注意:如果你需要字段排序,首先需要在生成的配置文件architecture.php中定义你需要的排序接收参数
在过滤类中必须实现接口 "IOrder"!!!
namespace App\Repositories\Filters\Admin;
use App\Repositories\Filters\{
AbstractFilter,
IOrder
};
// 需要排序,必须实现排序接口
class NameFilter extends AbstractFilter implements IOrder
{
// 过滤操作
public function filter($entity, $value)
{
return $entity->where('name', $value);
}
// 排序操作
public function order($entity, $direction)
{
return $entity->orderBy('name', $this->resolveOrderDirection($direction));
}
}
// 过滤name和email
http://www.phpno1.com/user?name=Anthony&[email protected]
// 过滤和排序组合。参数"o"是需要排序的字段key,value是排序规则 asc|desc,o参数是在architecture.php中配置的,可以定义多个参数。
http://www.phpno1.com/user?name=Anthony&[email protected]&o=desc
注意如果调用scope方法请注意,必须先调用再执行withCriteria进行过滤
//模型中定义
class User extends Model
{
public function scopeUserFields()
{
return $this->select(['id','name','email']);
}
}
//仓库中调用
class UserRepositoryEloquent extends AbstractRepository implements UserRepository
{
public function getUsers(int $perPage=0)
{
return $this->userFields()->withCriteria(
new FilterRequest($this->filters)
)->paginate($perPage);
}
}
//当Repository提供的method无法满足业务
public function do()
{
// 使用toEntity() 转换回Model或Build对象
return $this->repository
->toEntity()
->where(...)
->orWhere(...)
->when(...)
->get(...);
}
使用CacheGenerate的trait特性
用途:当使用redis或memcahce做缓存时,方便做数据缓存操作。当然,您也可以使用Laravel框架提供的Cache。
public function getUserList()
{
// 参数1:缓存的key值
// 缓存中有数据则从缓存中取,没有数据则从数据库取一次放入缓存。
$this->getOrCache('getUserList', function () {
return $this->paginate();
});
}