目前在二开一个商城, 要修改用户申请售后的问题
当前的逻辑 ( 用户申请售后 -> 后台拒绝退款 -> 用户端无法进行操作)
要修改成的逻辑 (用户申请售后 -> 后台拒绝退款 -> 用户继续申请售后 -> 后台继续进行审核…)
因为我已经给自己的号提交过退货并且拒绝了, 目前数据库退款记录的数据ID分别是 3
和 4
1.看接口
前端默认查询出来的数据是按照asc
进行排序
但是 后端的查询是按照 desc
来进行排序的
2.看代码
前端代码
$list = $this
.... 查询条件
->paginate(10, false, [
'query' => Request::instance()->request()
]);
foreach($list as $v){
// 如果是售后 则调用预载入
if($type == 4){
$v['sales'] = $v->sales;
}
}
后端代码
// 经过一系列调用 调用到了common
/**
* 订单详情
* @param $order_id
* @return null|static
* @throws \think\exception\DbException
*/
public static function detail($order_id)
{
return self::get($order_id, ['sales']);
}
在排查到sales
后发现这两个都最终汇聚到了 app\common\model\Order
下的预载入 sales
中
预载入代码
public function sales(){
return $this->hasOne('OrderSales','order_id','order_id');
}
我们并没有进行排序, 但是为什么前端是正常, 但后端是按照desc
来进行排序的呢?
我试着给预载入代码里面加入排序
public function sales(){
return $this->hasOne('OrderSales','order_id','order_id')->order("id desc");
}
然后邪门的来了, 前端和后端的排序同时被颠倒了.
接着往下看
因为目前前端的是正常的, 后端一直是反着来. 所以我们一步一步往下查.
根据self::get()
去找到 \thinkphp\library\think\Model.php
里面的 get()
然后里面的最终代码是$query->find($data)
我们去看一下 find()
这个方法
think\db\Query::find
里面找到预载入查询 $result->eagerlyResult($result, $options['with']);
接着找 think\Model::eagerlyResult
里面找到 $this->$relation()->eagerlyResult($result, $relation, $subRelation, $closure);
打印一下 $this->$relation()
打印出来 object(think\model\relation\HasOne)#83 (11)
接着去 HasOne
里面找 eagerlyResult
发现里面没有, 但是 HasOne
是继承了 OneToOne
的
接着找 命名空间\think\model\relation\OneToOne
通过打印知道了走的是 IN查询
所以 接着找 think\model\relation\OneToOne::eagerlyOne
找到这里后到头了
/**
* 预载入关联查询(数据)
* @param Model $result
* @param string $relation
* @param string $subRelation
* @param \Closure $closure
* @return mixed
*/
abstract protected function eagerlyOne(&$result, $relation, $subRelation, $closure);
那就谁继承的这个OneToOne
就去找谁 . 我们来到了 HasOne
里面
果然在这里!
打印下方代码的$data
我们如愿以偿的找到了最终的数据
$data = $this->eagerlyWhere($this->query, [$foreignKey => $result->$localKey], $foreignKey, $relation, $subRelation, $closure);
那就去开盒这个eagerlyWhere
它在OneToOne
中
/**
* 一对一 关联模型预查询(IN方式)
* @access public
* @param object $model 关联模型对象
* @param array $where 关联预查询条件
* @param string $key 关联键名
* @param string $relation 关联名
* @param string $subRelation 子关联
* @param bool|\Closure $closure
* @return array
*/
protected function eagerlyWhere($model, $where, $key, $relation, $subRelation = '', $closure = false)
{
$this->baseQuery = true;
// 预载入关联查询 支持嵌套预载入
if ($closure) {
call_user_func_array($closure, [ & $model]);
if ($field = $model->getOptions('with_field')) {
$model->field($field)->removeOption('with_field');
}
}
$list = $model->where($where)->with($subRelation)->select();
// 组装模型数据
$data = [];
foreach ($list as $set) {
$data[$set->$key] = $set;
}
return $data;
}
最终的原因找到了, 排序都是正确的. 但是这个eagerlyWhere
会取出查询出来的最后一条数据. 所以会造成排序颠倒的问题.
解决方案
protected function eagerlyWhere($model, $where, $key, $relation, $subRelation = '', $closure = false)
{
$this->baseQuery = true;
// 预载入关联查询 支持嵌套预载入
if ($closure) {
call_user_func_array($closure, [ & $model]);
if ($field = $model->getOptions('with_field')) {
$model->field($field)->removeOption('with_field');
}
}
$list = $model->where($where)->with($subRelation)->select();
// 组装模型数据
$data = [];
foreach ($list as $set) {
if(empty($data[$set->$key])){
$data[$set->$key] = $set;
}
}
return $data;
}
将上述代码替换, 核心部分
if(empty($data[$set->$key])){
$data[$set->$key] = $set;
}