150 lines
5.1 KiB
PHP
150 lines
5.1 KiB
PHP
<?php
|
||
namespace app\common\model;
|
||
|
||
use app\common\library\DatabaseRoute;
|
||
use think\db\BaseQuery;
|
||
use think\facade\Db;
|
||
use think\facade\Log;
|
||
use support\think\Model;
|
||
use think\db\Query;
|
||
|
||
class BaseModel extends Model
|
||
{
|
||
|
||
|
||
/**
|
||
* 查询前处理数据库连接
|
||
*/
|
||
public static function findbefore($model, $where):string
|
||
{
|
||
return DatabaseRoute::getConnection($model->getTable(), $where, false);
|
||
}
|
||
|
||
|
||
|
||
/**
|
||
* 写入数据前处理数据库连接
|
||
* @param array $data 写入的数据
|
||
* @return void
|
||
*/
|
||
protected static function onBeforeInsert($data)
|
||
{
|
||
$connection = DatabaseRoute::getConnection($data->getTable(), $data, true);
|
||
print_r($connection);
|
||
$data->setConnection($connection);
|
||
}
|
||
|
||
/**
|
||
* 更新数据前处理数据库连接
|
||
* @param array $data 更新的数据
|
||
* @return void
|
||
*/
|
||
protected static function onBeforeUpdate($data)
|
||
{
|
||
$connection = DatabaseRoute::getConnection($data->getTable(), $data->getWhere(), true);
|
||
$data->setConnection($connection);
|
||
}
|
||
|
||
|
||
/**
|
||
* 从查询选项中提取分库键的值(深度解析版)
|
||
*/
|
||
private static function extractKeyFromOptions(array $options, string $keyField)
|
||
{
|
||
$dbKey = null;
|
||
|
||
// 1. 处理顶级 where 条件
|
||
if (isset($options['where'])) {
|
||
$dbKey = static::parseWhereCondition($options['where'], $keyField);
|
||
if ($dbKey !== null) return $dbKey;
|
||
}
|
||
|
||
// 2. 处理 whereOr 条件
|
||
if (isset($options['whereOr'])) {
|
||
$dbKey = static::parseWhereCondition($options['whereOr'], $keyField);
|
||
if ($dbKey !== null) return $dbKey;
|
||
}
|
||
|
||
// 3. 处理软删除条件
|
||
if (isset($options['soft_delete']) && is_array($options['soft_delete'])) {
|
||
if ($options['soft_delete'][0] === $keyField) {
|
||
$dbKey = $options['soft_delete'][2] ?? null;
|
||
Log::info("条件类型3: 软删除条件中匹配到 {$keyField}={$dbKey}");
|
||
return $dbKey;
|
||
}
|
||
}
|
||
|
||
// 4. 处理字段绑定(bind)
|
||
if (isset($options['bind'][$keyField])) {
|
||
$dbKey = $options['bind'][$keyField];
|
||
Log::info("条件类型4: 绑定参数中匹配到 {$keyField}={$dbKey}");
|
||
return $dbKey;
|
||
}
|
||
|
||
// 5. 处理查询参数(param)
|
||
if (isset($options['param'][$keyField])) {
|
||
$dbKey = $options['param'][$keyField];
|
||
Log::info("条件类型5: 查询参数中匹配到 {$keyField}={$dbKey}");
|
||
return $dbKey;
|
||
}
|
||
|
||
// 6. 处理数据(data)- 适用于更新操作
|
||
if (isset($options['data'][$keyField])) {
|
||
$dbKey = $options['data'][$keyField];
|
||
Log::info("条件类型6: 数据中匹配到 {$keyField}={$dbKey}");
|
||
return $dbKey;
|
||
}
|
||
|
||
// 未找到分库键
|
||
Log::warning("条件解析失败: 未找到 {$keyField} 的值");
|
||
return null;
|
||
}
|
||
|
||
/**
|
||
* 解析 where 条件(处理 AND/OR 逻辑)
|
||
*/
|
||
private static function parseWhereCondition($where, string $keyField)
|
||
{
|
||
$dbKey = null;
|
||
|
||
// 处理数组形式的 where 条件
|
||
if (is_array($where)) {
|
||
foreach ($where as $index => $whereItem) {
|
||
// 1. 处理 AND/OR 逻辑分组
|
||
if (is_string($index) && in_array(strtoupper($index), ['AND', 'OR', 'NOT'])) {
|
||
Log::info("条件类型1: 发现 {$index} 逻辑分组,开始递归解析");
|
||
|
||
// 递归解析逻辑分组中的条件
|
||
$dbKey = static::parseWhereCondition($whereItem, $keyField);
|
||
if ($dbKey !== null) {
|
||
Log::info("条件类型1: {$index} 分组中匹配到 {$keyField}={$dbKey}");
|
||
return $dbKey;
|
||
}
|
||
} // 2. 处理 ['user_id', '=', 123] 形式
|
||
elseif (is_array($whereItem) && count($whereItem) >= 3) {
|
||
if ($whereItem[0] === $keyField) {
|
||
$dbKey = $whereItem[2];
|
||
Log::info("条件类型2: 直接匹配 {$keyField}={$dbKey}");
|
||
return $dbKey;
|
||
}
|
||
} // 3. 处理闭包条件: ['user_id', function($query){...}]
|
||
elseif (is_array($whereItem) && isset($whereItem[1]) && $whereItem[1] instanceof \Closure) {
|
||
Log::info("条件类型3: 发现闭包条件,开始递归解析");
|
||
|
||
// 创建临时查询对象执行闭包
|
||
$subQuery = new Query();
|
||
$whereItem[1]($subQuery);
|
||
|
||
// 递归解析闭包中的条件
|
||
$dbKey = static::extractKeyFromOptions($subQuery->getOptions(), $keyField);
|
||
if ($dbKey !== null) {
|
||
Log::info("条件类型3: 闭包中匹配到 {$keyField}={$dbKey}");
|
||
return $dbKey;
|
||
}
|
||
}
|
||
}
|
||
return null;
|
||
}
|
||
}
|
||
|
||
} |