houde_web_api/app/common/exception/Sort.php

204 lines
6.5 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
namespace app\common\exception;
use DateTime;
use think\facade\Request;
use think\facade\Log;
use think\helper\Arr;
use think\facade\Db;
use app\common\arw\adjfut\src\Exception\ErrorMsg;
/**
* 排序类(调用此类的方法需要进行事务与锁表操作)
*/
class Sort
{
/**
* 模型层实例
* @var \think\model
*/
private $model;
/**
* 主键字段名
* @var string
*/
private $pk;
/**
* 排序字段名
* @var string
*/
private $sort_field;
/**
* 表名
* @var string
*/
private $table_name;
/**
* 构造器
*
* @param string $model 模型命名空间
*/
public function __construct(string $model)
{
//模型实例化
$this->model = new $model();
//主键字段名初始化
$this->pk = $this->model->db()->getPk();
//表名初始化
$this->table_name = $this->model->db()->getTable();
//排序字段名初始化
$this->initSortField();
}
/**
* 获取排序字段名
*/
public function getSortField(): string
{
return $this->sort_field;
}
/**
* 排序号新增处理
*
* @param array $extra_wheres 关联类型 例:["xxx_type" => 1]
* @return int 返回新增所需的最新排序号
*/
public function add(array $extra_wheres = []): int
{
$sort_field = $this->sort_field;
$max_sort = $this->model->where($extra_wheres)->order($sort_field, 'desc')->value($sort_field) ?? 0;
return ++$max_sort;
}
/**
* 排序号互换处理(数据A <=> 数据B)
*
* @param string $guid 主键值
* @param int $sort 新排序号
* @param array $extra_wheres 关联类型 例:["xxx_type" => 1]
*/
public function swap(string $guid, int $sort, array $extra_wheres = []): void
{
$model = $this->model;
$table_name = $this->table_name;
$pk = $this->pk;
$sort_field = $this->sort_field;
//数据A
$data_a = $model->where($pk, $guid)->find();
if (!$data_a) {
throwErrorMsg('Tool::sortEditProc() : 找不到该数据原排序号', 444);
}
//数据B
//查找当前数据所想更换的新排序号是否已有数据占用(排除自己)这个占用数据则视为数据B
$data_b = $model->where($sort_field, $sort)->where($pk, '<>', $guid)->where($extra_wheres)->find();
//数据B存在开始进行互换处理
if ($data_b) {
//【互换内容初始化】
$update_data = [];
//检查模型是否有父祖级主键,有则也加入互换
if ($this->isExistFathersAndAncestors()) {
$update_data[$model->parent_guid_field] = $data_a[$model->parent_guid_field];
$update_data[$model->ancestors_guid_field] = $data_a[$model->ancestors_guid_field];
}
//原字段排序加入互换
$update_data = [$sort_field => $data_a[$sort_field]];
//关联类型也加入互换
foreach ($extra_wheres as $key => $value) {
$update_data[$key] = $data_a[$key];
};
//【数据逻辑处理】
//互换数据A与B的关联类型不相同时候,则代表为数据互换跨类型情况
if (self::isAssociationTypeDataSame($data_a, $data_b, $extra_wheres)) {
//数据互换不同类型情况-正常互换操作
Db::name($table_name)->where($sort_field, $sort)->where($extra_wheres)->update($update_data);
} else {
//数据互换跨类型情况-腾位操作
$this->vacate($sort, $extra_wheres);
}
}
}
/**
* 排序号腾位处理
*
* @param int|null $sort 当前排序号
* @param array $wheres 当前指定数据的额外查询条件(tp批量查询数组) 例:["xxx_type" => 1,...]
*/
public function vacate($sort, array $wheres = []): void
{
$sort_field = $this->sort_field;
$table_name = $this->table_name;
//新增数据的所属排序号已有数据占用,则腾位处理(已占用的数据及其后面所有数据一起排序号腾位+1)
if ($this->model->where($sort_field, $sort)->where($wheres)->value($sort_field) !== null) {
Db::name($table_name)->where($wheres)->where($sort_field, '>=', $sort)->inc($sort_field)->update();
}
}
/**
* 排序号退位处理
*
* @param string $guid 当前主键值
* @param array $correl_fields 关联类型字段 例:["xxx_guid",...] 代表删除排序号时会根据这些字段来关联(例:所属xxx类型、所属xxx系列)来进行排序处理
*/
public function back(string $guid, array $correl_fields): void
{
$model = $this->model;
$sort_field = $this->sort_field;
//在所删除的数据之后的数据所属排序号将进行减位处理减位-1
$deleted_find = $model->where($this->pk, $guid)->find();
if ($deleted_find) {
$con = [];
foreach ($correl_fields as $correl_field) {
$con[$correl_field] = $deleted_find[$correl_field];
}
$model->where($sort_field, '>', $deleted_find[$sort_field])->where($con)->dec($sort_field)->save();
}
}
/**
* 对比数据关联类型是否相同【排序号互换处理】
*
* @param object $data_a 互换数据A
* @param object $data_b 互换数据B
* @param array $extra_wheres 关联类型数组 例:["xxx_type" => 1]
*/
private static function isAssociationTypeDataSame(object $data_a, object $data_b, array $extra_wheres): bool
{
foreach ($extra_wheres as $key => $val) {
if ($data_a[$key] != $data_b[$key]) {
return false;
}
};
return true;
}
/**
* 检查模型实例父祖级主键字段是否存在【排序号互换处理】
*/
private function isExistFathersAndAncestors(): bool
{
return isset($this->model->parent_guid_field) && isset($this->model->ancestors_guid_field);
}
/**
*初始化排序字段名
*/
private function initSortField(): void
{
if (!isset($this->model->order_field)) {
throwErrorMsg('排序处理失败!模型层未定义排序字段$order_field');
}
$this->sort_field = $this->model->order_field;
}
}