- 封装验证基类
BaseValidate
类,便于以后模块的复用和程序扩展 ; 【例如】banner
的验证类BannerValidator
继承于BaseValidate
基类 ,可以复用基类的方法,便于扩展,详细见代码BannerController
;
可以参考【模仿】一下优秀的API设计:
RESTFul API 的合理使用(切勿盲目照搬标准的REST)
全局异常的处理
- 记录日志
- 统一的异常信息格式化,
message
,error_code
等;尽量不要使用500状态码
- 一对一怎么定义
一对一的关系要定义在
主动调用的调用方
例如:本项目中theme
和image
两个模型是一对一关系,实际业务中,我们需要从theme
模型去调用image
模型中的图片, 所以定义模型关系需要定义在theme
中:
theme.php
/**
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
*/
public function topicImage()
{
return $this->belongsTo('App\Models\Images', 'topic_img_id', 'id');
}
hasOne
和belongsTo
的区别:
hasOne
和belongsTo
是有主从的或者说不能互换的; 为撒?在设计表结构时,两个有一对一关系的模型中,一个表中会设计外键,而另一表中不会设计外键,需要用
hasOne
和belognsTo
来区分
本项目中theme
表中有topic_img_id
对应image
表中的id
; 而image
表中没有定义外键,类似于theme_id
的字段; 从这点来说,这一对一的关系是不能互换,不对等的;
theme 表
image 表
theme.php
/**
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
*/
public function topicImage()
{
return $this->belongsTo('App\Models\Images', 'topic_img_id', 'id');
}
- 总结:
- 一对一关系中,一对一的关系模型定义在
调用的主动方
模型中,上述中的theme
模型; - 一对一关系中,在有外键的模型中 使用
belongsTo
; 没有外键的模型 使用hasOne
;
- 在
app
目录下新建一个Support
目录【自定义名称】, 然后在该目录下新建helpers.php
文件; - 在根目录下
composer.json
中的autoload
选项中添加files
json对象,对应步骤1
新建的helpers.php
注意命名空间 ,下面示例
"autoload": {
"files":[
"app/Support/helpers.php"
],
"classmap": [
"database/seeds",
"database/factories"
],
"psr-4": {
"App\\": "app/"
}
},
注意:这里注意遵循 prs-4
命名空间规范;
3. 命令行模式下执行 composer dump-autoload
命令,用于重新加载 composer.json
文件;
- 安装: 使用命令安装扩展包
composer require predis/predis
注意
debug
:
Laravel5.6
文档中:
先前弃用的optimizeArtisan命令已被删除。随着PHP本身(包括OPcache)的最新改进,该 optimize命令不再提供任何相关的性能优势。因此,您可以php artisan optimize从scripts 您的composer.json文件中删除 。
将 php artisan optimize
删除就行了
- 在
product
模型中声明一个和productImages
的一对多的关系 而productImages
模型同时又和image
是一对一的关系; - 如果在
product
模型查询中关联productImages
查出image
中的字段,此时就要使用模型嵌套
可以在查询中使用with(['productImages.image']);
示例代码:
public function getProductDetail($id)
{
try{
$res = new ProductProperty($this->productModel::with(['productImages.image', 'productProperty'])->find($id));
}catch (\Exception $exception){
throw new ModelNotFoundException('商品不存在');
}
return $res;
}
- 嵌套查询中的排序:
public function getProductDetail($id)
{
try{
$res = new ProductProperty(
$this->productModel->with([
'productImages' => function ($query) {
return $query->with(['image'])->orderBy('order', 'asc');
}])
->with(['productProperty'])
->find($id)
);
}catch (\Exception $exception){
throw new ModelNotFoundException('商品不存在');
}
return $res;
}
使用中间件做权限控制:项目中使用 scope
参数来控制访问权限
- 首先生成访问中间件文件,使用命令
php artisan make:middleware CheckPrimaryScope
- 编写
App\Http\Middleware\CheckPrimaryScope.php
中的handle
方法;
//CheckPrimaryScope.php 获取缓存中的scope值,进行判断用户的访问权限
public function handle($request, Closure $next)
{
if (TokenRepository::getCurrentTokenVar('scope')){
if (TokenRepository::getCurrentTokenVar('scope') >= ScopeEnum::USER){
return $next($request);
}else{
throw new ForbiddenException('暂无访问权限');
}
}else{
throw new TokenException('token无效或已过期');
}
}
- 在
App\Http\Kernel.php
文件中注册中间件,在$routeMiddleware
属性中加入自定的中间件文件
protected $routeMiddleware = [
'auth' => \Illuminate\Auth\Middleware\Authenticate::class,
'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,
'bindings' => \Illuminate\Routing\Middleware\SubstituteBindings::class,
'cache.headers' => \Illuminate\Http\Middleware\SetCacheHeaders::class,
'can' => \Illuminate\Auth\Middleware\Authorize::class,
'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class,
'signed' => \Illuminate\Routing\Middleware\ValidateSignature::class,
'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
'primaryScope' => CheckPrimaryScope::class,
];
- 在需要控制访问权限的控制器中使用
__construct
构造函数的middleware
属性中声明就可以使用;
public function __construct()
{
$this->middleware('primaryScope')->only('createOrUpdate');
}
示例代码中中间件的作用仅对 createOrUpdate
方法生效
- 这里注意
only
和except
only
: 设置中间件应该应用的控制器方法; 需要作用于多个方法可以使用 数组的形式 []except
: 设置中间件应该排除的控制器方法; 需要作用于多个方法可以使用 数组的形式 []
public function __construct()
{
$this->middleware('primaryScope')->only(['create', 'update']);
}
示例代码中中间件的作用会对 create
和 update
方法生效;
处理订单思路
- 用户在选择商品后,向api提交包含它所选商品的相关信息。
- api接受商品信息后,检测订单相关商品的库存量[客户端信息和服务器的信息数据不是实时同步,(选择商品后,订单提交之前 缺货)]。
- 如果有库存,就把订单信息保存到数据库中等同于下单成功,返回客户端消息,告诉客户端可以进行支付。
- 客户端接受“可以支付消息”,调用支付接口,进行支付操作。
- 进行支付,扣款之前再次检测库存量(下单之后允许在一定时间段内进行支付{付款})。
- 库存量检测通过服务器调用微信的支付接口进行支付。
- 小程序根据服务器返回参数拉去支付 【在调用支付和支付成功之间再次检测库存量,可能会在调用之后缺货】,发生的概率很小。可忽略
- 微信会返回一个支付结果,根据微信的返回结果判断是否支付成功。【异步调用】
- 如果微信返回支付成功,对库存量进行对应的扣除,如果微信返回支付失败,返回一个支付失败的结果【返回客户端支付成功与否是微信返回的。】