This commit is contained in:
ASUS 2025-08-13 14:12:31 +08:00
parent c95616561f
commit 34da927bc9
10 changed files with 2021 additions and 23 deletions

1
.gitignore vendored
View File

@ -4,5 +4,6 @@
/vendor
*.log
.env
.idea
/tests/tmp
/tests/.phpunit.result.cache

View File

@ -10,7 +10,7 @@
<option name="highlightLevel" value="WARNING" />
<option name="transferred" value="true" />
</component>
<component name="PhpProjectSharedConfiguration" php_language_level="7.0" />
<component name="PhpProjectSharedConfiguration" php_language_level="8.2" />
<component name="PhpStanOptionsConfiguration">
<option name="transferred" value="true" />
</component>

135
app/DbCoroutineContext.php Normal file
View File

@ -0,0 +1,135 @@
<?php
namespace app;
class DbCoroutineContext
{
// 协程隔离数据
protected static array $data = [];
protected static array $list = [];
// 普通环境全局数据
protected static array $globalData = [];
protected static array $globalList = [];
protected static function getCid(): ?int
{
if (class_exists('\Swoole\Coroutine')) {
$cid = \Swoole\Coroutine::getCid();
if ($cid >= 0) {
return $cid;
}
}
return null;
}
// put 存数据到 list
public static function put(mixed $value): void
{
$val = self::get('startTrans');
if (!empty($val) && $val === true) {
$value->startTrans();
}
$cid = self::getCid();
if ($cid !== null) {
self::$list[$cid][] = $value;
} else {
self::$globalList[] = $value;
}
}
// set 设置 key-value
public static function set(string $key, mixed $value): void
{
$cid = self::getCid();
if ($cid !== null) {
self::$data[$cid][$key] = $value;
} else {
self::$globalData[$key] = $value;
}
}
// get 获取 key-value
public static function get(string $key, mixed $default = null): mixed
{
$cid = self::getCid();
if ($cid !== null) {
return self::$data[$cid][$key] ?? $default;
} else {
return self::$globalData[$key] ?? $default;
}
}
// 获取 list
public static function getList(): array
{
$cid = self::getCid();
if ($cid !== null) {
return self::$list[$cid] ?? [];
} else {
return self::$globalList;
}
}
// 删除指定 key
public static function delete(string $key): void
{
$cid = self::getCid();
if ($cid !== null) {
unset(self::$data[$cid][$key]);
} else {
unset(self::$globalData[$key]);
}
}
public static function clearList()
{
foreach (self::getList() as $conn) {
try {
$conn->query('SELECT 1');
$conn->close();
// 连接正常
} catch (\Exception $e) {
}
}
$cid = self::getCid();
if ($cid !== null) {
unset(self::$list[$cid]);
} else {
self::$globalList = [];
}
}
public static function rollback()
{
foreach (self::getList() as $conn) {
$conn->rollback();
}
}
// 清理当前上下文
public static function clear(): void
{
foreach (self::getList() as $conn) {
try {
$conn->query('SELECT 1');
$conn->close();
// 连接正常
} catch (\Exception $e) {
}
}
$cid = self::getCid();
if ($cid !== null) {
unset(self::$data[$cid], self::$list[$cid]);
} else {
self::$globalData = [];
self::$globalList = [];
}
}
public static function commit()
{
foreach (self::getList() as $conn) {
$conn->commit();
}
}
}

View File

@ -2,31 +2,192 @@
namespace app\controller;
use app\api\model\CourseCollect;
use app\api\model\CourseDetails;
use app\api\model\TbUser;
use app\model\DatabaseRoute;
use app\model\Test;
use support\Request;
use think\facade\Db;
use think\facade\Log;
class IndexController
{
public function index(Request $request)
{
return <<<EOF
<style>
* {
padding: 0;
margin: 0;
$get['courseId'] = $course_id = '1877654905222135809';
$user['user_id'] = $user_id = '14240';
$user = DatabaseRoute::getDb('tb_user', $user_id)->find();
try {
if(empty($get['courseId'])) {
return json('参数不完整');
}
iframe {
border: none;
overflow: scroll;
$courseId = $get['courseId'];
// 获取短剧详情
$dd_b = Db::connect('duanju_slave');
$db_name = $dd_b->name('course');
$bean = $db_name->where(['course_id' => $courseId])->find();
if(!$bean) {
return json('短剧不存在');
}
$courseCollect = DatabaseRoute::getDb('course_collect', $user_id)
->where(['course_id' => $course_id])
->where(['user_id' => $user_id])
->where(['classify' => 3])
->limit(1)
->find();
// 是否追剧
$collect = DatabaseRoute::getDb('course_collect', $user_id)
->where(['course_id' => $course_id])
->where(['classify' => 1])
->limit(1)
->find();
$db = Db::connect(config('think-orm.search_library'));
$userVip = $db->name('user_vip')->where(['user_id' => $user['user_id']])->find();
if ($userVip) {
$user['member'] = $userVip['is_vip'];
$user['end_time'] = $userVip['end_time'];
}
$userInfo = $user;
if (!empty($userInfo['member']) && $userInfo['member'] == 2) {
$isVip = true;
}else{
$isVip = false;
}
// 查询用户是否购买了整集
$courseUser = DatabaseRoute::getDb('course_user', $user_id)
->where(['course_id' => $course_id])
->where(['classify' => 1])
->find();
// 每天购买超过上限,获得免费时间段资格
$freeWatch = Test::checkFreeWatchPayCount($user['user_id']);
$startSort = 0;
$endSort = 5;
$dn_course_details = DatabaseRoute::getDb('course_details', ['course_id' => $courseId]);
$sort = null;
if (is_null($sort)) {
if (!empty($courseCollect)) {
$courseDetails = $dn_course_details->field('sort')
->where('course_details_id', $courseCollect['course_details_id'])
->limit(1)
->find();
$sort = $courseDetails['sort'];
}
}
if ($freeWatch || !empty($courseUser)) {
$courseDetailsSetVos = Test::courseSets($courseId, 2, null);
} else {
$courseDetailsSetVos = Test::courseSets($courseId, 1, $bean['wholesale_price']);
}
// 调整集数范围
if (!is_null($sort) && $sort > 2) {
$startSort = $sort - 3;
$endSort = $sort + 3;
if (count($courseDetailsSetVos) < $endSort) {
$startSort = count($courseDetailsSetVos) - 5;
$endSort = count($courseDetailsSetVos) + 1;
}
}
// 已购买剧集ID集合
$detailsId = [];
if (!$freeWatch) {
$det_db = Db::connect(DatabaseRoute::getConnection('course_user', ['user_id' => $user['user_id']]));
$detailsId = $det_db->name('course_user')->where(['course_id' => $courseId, 'classify' => 2])->column('course_details_id');
$det_db->close();
$detailsId = array_flip(array_flip($detailsId)); // 去重
}
// 处理剧集列表
$current = null;
foreach ($courseDetailsSetVos as &$s) {
$s['wholesalePrice'] = (int) $s['wholesalePrice'];
// 当前播放集
if (!empty($courseCollect) && $s['courseDetailsId'] == $courseCollect['course_details_id']) {
$s['current'] = 1;
$current = &$s;
}
// 非免费用户的权限控制
if (
!$freeWatch &&
$s['sort'] > 3 &&
(empty($detailsId) || !in_array($s['courseDetailsId'], $detailsId)) &&
empty($courseUser) &&
!$isVip
) {
$s['videoUrl'] = null;
}
// 检查是否已点赞
if ($s['sort'] > $startSort && $s['sort'] < $endSort) {
$isGood_db = Db::connect(DatabaseRoute::getConnection('course_collect', ['user_id' => $user['user_id']]));
$isGood = $isGood_db->name('course_collect')
->where('course_details_id', $s['courseDetailsId'])
->where('classify', 2)
->limit(1)
->count();
$isGood_db->close();
$s['isGood'] = empty($isGood) || $isGood == 0 ? 0 : 1;
}
}
// 如果没有当前播放集,默认第一集
if (empty($current) && !empty($courseDetailsSetVos)) {
$courseDetailsSetVos[0]['current'] = 1;
$current = &$courseDetailsSetVos[0];
}
Test::setCourseView($bean);
$price = ($freeWatch ? 0 : ($bean['price'] ?? 0));
$price = bccomp($price, '0', 2) <= 0 ? 0 : $price;
// 返回结果
$map = [
'current' => $current,
'price' => $price,
'title' => $bean['title'],
'collect' => empty($collect) || $collect == 0 ? 0 : 1,
'list' => $courseDetailsSetVos
];
return json($map);
} catch (\Exception $e) {
return json($e->getMessage());
}
</style>
<iframe
src="https://www.workerman.net/wellcome"
width="100%"
height="100%"
allow="*"
sandbox="allow-scripts allow-same-origin"
></iframe>
EOF;
}
public function view(Request $request)

516
app/model/DatabaseRoute.php Normal file
View File

@ -0,0 +1,516 @@
<?php
namespace app\model;
use app\DbCoroutineContext;
use think\Collection;
use think\db\Connection;
use think\facade\Cache;
use think\facade\Db;
use think\facade\Log;
class DatabaseRoute
{
/**
* 跨所有分库分页(自动 count自动追加 LIMIT ORDER BY
*
* @param \Closure $sqlBuilder 生成基础 SQL 的闭包函数(不包含 LIMIT
* @param int $page 当前页码
* @param int $pageSize 每页条数
* @param string|null $orderCol 排序字段(全局排序使用)
* @return array
*/
public static function paginateAllDbBySqlAutoCount(
\Closure $sqlBuilder,
int $page = 1,
int $pageSize = 20,
string $orderCol = null,
int $count = null,
): array
{
$dbMap = config('database.db_map');
$counts = [];
$total = 0;
if ($count === null) {
// 1. 自动 count 分库总数
$dbList = DatabaseRoute::getAllSelectDb();
foreach ($dbMap as $connName) {
if (in_array($connName, $dbList) ) {
$baseSql = call_user_func($sqlBuilder, $connName);
$countSql = self::buildCountSql($baseSql);
$count = Db::connect($connName)->query($countSql)[0]['count'] ?? 0;
$counts[$connName] = $count;
$total += $count;
}
}
}
if ($total === 0) {
return [
'list' => [],
'totalCount' => 0,
'totalPage' => 0,
'currPage' => $page,
'pageSize' => $pageSize,
];
}
$offset = ($page - 1) * $pageSize;
if ($offset >= $total) {
return [
'list' => [],
'totalCount' => $total,
'totalPage' => (int)ceil($total / $pageSize),
'currPage' => $page,
'pageSize' => $pageSize,
];
}
$limit = $pageSize;
$allRows = [];
$skip = $offset;
// 2. 分库分页查询
foreach ($counts as $connName => $count) {
if ($count <= 0) continue;
if ($skip >= $count) {
$skip -= $count;
continue;
}
$localOffset = $skip;
$localLimit = min($count - $localOffset, $limit);
$baseSql = call_user_func($sqlBuilder, $connName);
$sql = rtrim($baseSql, ';');
if ($orderCol) {
$sql .= " ORDER BY {$orderCol} DESC";
}
$sql .= " LIMIT {$localOffset}, {$localLimit}";
$rows = Db::connect($connName)->query($sql);
$allRows = array_merge($allRows, $rows);
$limit -= $localLimit;
$skip = 0;
if ($limit <= 0) break;
}
// 3. 全局排序(若指定排序字段)
if ($orderCol) {
usort($allRows, function ($a, $b) use ($orderCol) {
return strtotime($b[$orderCol]) <=> strtotime($a[$orderCol]);
});
}
// 4. 返回结构
return [
'list' => $allRows,
'totalCount' => $total,
'totalPage' => (int)ceil($total / $pageSize),
'currPage' => $page,
'pageSize' => $pageSize,
];
}
/**
* SELECT SQL 自动构建对应的 COUNT SQL
*
* @param string $sql
* @return string
*/
private static function buildCountSql(string $sql): string
{
$sql = preg_replace('/\s+ORDER\s+BY\s+.+?$/i', '', $sql);
$sql = preg_replace('/\s+LIMIT\s+\d+(\s*,\s*\d+)?$/i', '', $sql);
if (preg_match('/FROM\s+(.*)/i', $sql, $matches)) {
return 'SELECT COUNT(*) AS count FROM ' . $matches[1];
}
throw new \RuntimeException("无法从 SQL 自动构建 COUNT 查询,请检查 SQL 是否规范");
}
public static function paginateDb(
string $table,
\Closure $builder,
int $page = 1,
int $pageSize = 20,
string|array $keyInfo = null,
$isRecords = false
) {
// 构建基础查询
if ($keyInfo) {
$query = self::getDb($table, $keyInfo);
}else{
$query = Db::table($table);
}
$builder($query); // 应用外部闭包设置查询条件,如 where/order 等
// 获取总数
$totalCount = (clone $query)->count();
// 计算总页数
$totalPage = (int) ceil($totalCount / $pageSize);
$currPage = max(1, min($page, $totalPage));
// 获取分页数据
$list = $query
->page($currPage, $pageSize)
->select()
->toArray();
$query->getConnection()->close();
return [
'totalCount' => $totalCount,
'pageSize' => $pageSize,
'totalPage' => $totalPage,
'currPage' => $currPage,
$isRecords ? 'records' : 'list' => convertToCamelCase($list),
];
}
/**
* 跨所有从库分页(支持游标分页和传统页码分页)
* @param string $table 表名
* @param \Closure $builder 查询构造器
* @param int|null $page 当前页null 表示使用游标分页)
* @param int $pageSize 每页条数
* @param string|null $lastCreateTime 游标分页的游标值create_time
* @return array [list, total|nextCursor, hasMore]
*/
public static function paginateAllDb(
string $table,
\Closure $builder,
int $page = 1,
int $pageSize = 20,
string $orderCol = 'create_time',
string $modelOrderCol = null,
bool $isRecords = false
): array
{
$dbMap = config('database.db_map');
$counts = [];
$total = 0;
// 1. 统计每个分库总数
$dbList = DatabaseRoute::getAllSelectDb();
foreach ($dbMap as $connName) {
if (in_array($connName, $dbList) ) {
$query = Db::connect($connName)->name($table);
$query = call_user_func($builder, $query);
// 不要order避免报错
$query->removeOption('order');
$count = $query->count();
$query->getConnection()->close();
$counts[$connName] = $count;
$total += $count;
}
}
if ($total === 0) {
return [
$isRecords ? 'records' : 'list' => [],
'totalCount' => 0,
'totalPage' => 0,
'currPage' => $page,
'pageSize' => $pageSize,
];
}
$offset = ($page - 1) * $pageSize;
if ($offset >= $total) {
// 超出总数,返回空数据
return [
$isRecords ? 'records' : 'list' => [],
'totalCount' => $total,
'totalPage' => (int)ceil($total / $pageSize),
'currPage' => $page,
'pageSize' => $pageSize,
];
}
$limit = $pageSize;
$allRows = [];
// 2. 计算每个库需要查询的偏移和条数
$skip = $offset; // 还需要跳过多少条
foreach ($counts as $connName => $count) {
if ($count <= 0) continue;
if ($skip >= $count) {
// 跳过整个分库
$skip -= $count;
continue;
}
// 本库要查询的起始 offset
$localOffset = $skip;
// 本库剩余条数
$localLimit = min($count - $localOffset, $limit);
// 查询数据
$query = Db::connect($connName)->name($table);
$query = call_user_func($builder, $query);
$rows = $query->order($orderCol, 'desc')
->limit($localOffset, $localLimit)
->select()
->toArray();
$query->getConnection()->close();
$allRows = array_merge($allRows, $rows);
$limit -= $localLimit; // 剩余要查询的条数
$skip = 0; // 之后库不再跳过
if ($limit <= 0) break; // 已查够
}
// 3. 全局排序(降序)
if ($modelOrderCol) {
usort($allRows, function ($a, $b) use ($modelOrderCol) {
return strtotime($b[$modelOrderCol]) <=> strtotime($a[$modelOrderCol]);
});
}
// 4. 返回分页数据
return [
$isRecords ? 'records' : 'list' => $allRows,
'totalCount' => $total,
'totalPage' => (int)ceil($total / $pageSize),
'currPage' => $page,
'pageSize' => $pageSize,
];
}
/**
* 对所有从库执行事务XA 分布式模拟,非真实两阶段提交)
* @param \Closure $callback
* @return mixed
* @throws \Throwable
*/
public static function transactionXa(\Closure $callback)
{
DbCoroutineContext::set('startTrans', true);
try {
// 执行用户操作(传入事务闭包)
$result = call_user_func($callback);
// 提交所有连接
DbCoroutineContext::commit();
return $result;
} catch (\Throwable $e) {
// 回滚所有连接
DbCoroutineContext::rollback();
Log::error("transactionXa 全部回滚:" . $e->getMessage());
Log::info('错误信息'.$e->getMessage().'具体信息'.$e->getTraceAsString());
throw $e;
}finally {
DbCoroutineContext::clearList();
DbCoroutineContext::set('startTrans', false);
}
}
public static function getMasterDb($table, $isWrite = false)
{
$conn = Db::connect();
if ($isWrite) {
DbCoroutineContext::put($conn);
}
return $conn->name($table);
}
/**
* 根据表和分库值获取db
* @param $table string 表名
* @param $keyInfo string | array
*/
public static function getDb($table, $keyInfo, $isWrite = false, $isUpdate = false, $addWhere = true)
{
if (is_array($keyInfo)) {
$con = Db::connect(DatabaseRoute::getConnection($table, $keyInfo, $isWrite));
if ($isWrite) {
DbCoroutineContext::put($con);
}
$model = $con->name($table);
if ($addWhere && (!$isWrite || $isUpdate)) {
$model->where($keyInfo);
}
} else {
$con = Db::connect(DatabaseRoute::getConnection($table, ['user_id' => $keyInfo], $isWrite));
if ($isWrite) {
DbCoroutineContext::put($con);
}
$model = $con->name($table);
if ($addWhere && (!$isWrite || $isUpdate)) {
$model->where([
'user_id' => $keyInfo
]);
}
}
return $model;
}
/**
* 跨所有分库直接删除(危险操作,务必确认条件准确)
* @param string $table 表名
* @param \Closure $builder 条件构造器,如 function($query) { return $query->where('xxx', xxx); }
* @return int 删除的总记录数
*/
public static function deleteAllDbDirect(string $table, \Closure $builder): int
{
$dbMap = config('database.db_master_map');
$totalDeleted = 0;
foreach ($dbMap as $connName) {
if ($connName === 'duanju_master') continue;
$query = Db::connect($connName)->name($table);
$query = call_user_func($builder, $query);
$deleted = $query->delete();
$query->getConnection()->close();
$totalDeleted += $deleted;
}
return $totalDeleted;
}
public static function getAllDbData($table, \Closure $builder)
{
return new class($table, $builder) {
protected $table;
protected $builder;
protected $dbMap;
protected $masterDbMap;
public function __construct($table, $builder)
{
$this->table = $table;
$this->builder = $builder;
$this->dbMap = config('database.db_map');
$this->masterDbMap = config('database.db_master_map');
}
public function __call($method, $args)
{
$finalResult = null;
try {
if ($method == 'insert') {
throw new \RuntimeException("不支持insert");
}
// insert 和 update 使用主库
if ($method == 'update' || $method == 'delete') {
foreach ($this->masterDbMap as $dbname) {
if ($dbname !== 'duanju_master') {
$query = Db::connect($dbname)->name($this->table);
$query = call_user_func($this->builder, $query);
if (method_exists($query, $method)) {
$result = call_user_func_array([$query, $method], $args);
$finalResult = $result;
$query->getConnection()->close();
// find 返回 nullselect 返回空数组count 返回数字
if ($result || $result === 0) {
return $result;
}
}else {
$query->getConnection()->close();
}
}
}
return $finalResult;
}else{
$dbList = DatabaseRoute::getAllSelectDb();
foreach ($this->dbMap as $dbname) {
if (in_array($dbname, $dbList) ) {
$query = Db::connect($dbname)->name($this->table);
$query = call_user_func($this->builder, $query);
if (method_exists($query, $method)) {
$result = call_user_func_array([$query, $method], $args);
// find 返回 nullselect 返回空数组count 返回数字
$finalResult = $result;
$query->getConnection()->close();
if ($result instanceof Collection) {
if (!$result->isEmpty()) {
return $result;
}
}elseif (is_int($result) && $result != 0) {
return $result;
} else if ($result) {
return $result;
}
}else {
$query->getConnection()->close();
}
}
}
}
}catch (\Throwable $e) {
Log::error("错误信息".$e->getMessage());
throw $e;
}
return $finalResult;
}
};
}
public static function getAllSelectDb()
{
$index = self::getIndex();
return ["duanju$index-0_slave", "duanju$index-1_slave", "duanju$index-2_slave", "duanju$index-3_slave", "duanju$index-4_slave"];
}
private static function getIndex()
{
$INDEX = \cache('db_index');
if ($INDEX == null) {
$INDEX = 0;
}
$INDEX = ++$INDEX % 4;
\cache('db_index', $INDEX);
return $INDEX;
}
/**
* 获取数据库连接
* @param string $tableName 表名
* @param array $data 数据
* @param bool $isWrite 是否为写操作
* @return Connection
*/
public static function getConnection($table, $data = [], $isWrite = false)
{
$routeConfig = config('think-orm.route');
$keyField = strpos($table, 'user') !== false || in_array($table, [
'orders', 'course_collect', 'pay_details', 'disc_spinning_record',
'cash_out', 'course_user', 'tb_user', 'task_center_record',
'user_money', 'user_sign_record', 'invite_achievement',
'invite_money', 'user_info', 'sys_user', 'user_money_details', 'sys_user_money_details'
]) ? 'user_id' : 'course_id';
if (!isset($data[$keyField])) {
Log::warning("分库警告: 表={$table}, 数据中缺少 {$keyField} 字段");
return $isWrite ? 'duanju_master' : 'duanju_slave';
}
$index = abs($data[$keyField] % 5);
$connectionTemplate = $isWrite
? $routeConfig[$table]['master']
: $routeConfig[$table]['slave'];
$connectionName = str_replace("{\${$keyField}%5}", $index, $connectionTemplate);
return $connectionName;
}
}

View File

@ -2,7 +2,8 @@
namespace app\model;
use support\Model;
use think\model;
use think\facade\Db;
class Test extends Model
{
@ -26,4 +27,84 @@ class Test extends Model
* @var bool
*/
public $timestamps = false;
public static function checkFreeWatchPayCount($userId)
{
$count = DatabaseRoute::getDb('orders', $userId)->where([
'status' => 1,
'pay_way' => 9,
['create_time', '>', date('Y-m-d 00:00:00')],
])->count();
$needCount = Db::name('common_info')->where([
'type' => 916
])->find();
$freeTime = Db::name('common_info')->where([
'type' => 917
])->find();
if (!$needCount || !$freeTime) {
return false;
}
if ($count >= intval($needCount['value'])) {
$isExpire = false;
}else{
$isExpire = true;
}
return !$isExpire;
}
public static function courseSets($courseId, $isPrice, $wholesalePrice)
{
$db = Db::connect(DatabaseRoute::getConnection('course_details', ['course_id' => $courseId]));
$courseDetailsSetVos = $db->name('course_details')
->alias('c')
->field([
'c.course_id' => 'courseId',
'c.course_details_id' => 'courseDetailsId',
'c.course_details_name' => 'courseDetailsName',
'c.video_url' => 'videoUrl',
'c.price' => 'price',
'c.sort' => 'sort',
'c.is_price' => 'isPrice',
'c.title_img' => 'titleImg',
'c.good_num' => 'goodNum',
])
->where('c.course_id', $courseId)
->order('c.sort', 'asc')
->select()
->toArray();
foreach ($courseDetailsSetVos as $k => &$v) {
$v['courseId'] = (string) $v['courseId'];
$v['courseDetailsId'] = (string) $v['courseDetailsId'];
if(empty($wholesalePrice)) {
$v['wholesalePrice'] = 0;
}else {
$v['wholesalePrice'] = $wholesalePrice;
}
if($isPrice != 1) {
$v['isPrice'] = 2;
}
}
return $courseDetailsSetVos;
}
public static function setCourseView($course)
{
// 1. 更新总播放量
if (empty($course['view_counts'])) {
$viewCounts = 1;
} else {
$viewCounts = $course['view_counts'] + 1;
}
$db_name = Db::connect(config('think-orm.z_library'))->name('course');
// 4. 执行数据库更新
$db_name->where(['course_id' => $course['course_id']])->update([
'view_counts' => $viewCounts,
'week_view' => 999
]);
}
}

View File

@ -26,7 +26,9 @@
"require": {
"php": ">=8.1",
"workerman/webman-framework": "^2.1",
"monolog/monolog": "^2.0"
"monolog/monolog": "^2.0",
"webman/think-orm": "^2.1",
"vlucas/phpdotenv": "^5.6"
},
"suggest": {
"ext-event": "For better performance. "

819
composer.lock generated
View File

@ -4,8 +4,77 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "691f538563ac6695008ddc51b7722c80",
"content-hash": "31b009f9f2392b9eda909c76dbca259f",
"packages": [
{
"name": "graham-campbell/result-type",
"version": "1.1.x-dev",
"source": {
"type": "git",
"url": "https://github.com/GrahamCampbell/Result-Type.git",
"reference": "9d6c1d7ce69a3329936e603617e59ba205ab0a66"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/GrahamCampbell/Result-Type/zipball/9d6c1d7ce69a3329936e603617e59ba205ab0a66",
"reference": "9d6c1d7ce69a3329936e603617e59ba205ab0a66",
"shasum": "",
"mirrors": [
{
"url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%",
"preferred": true
}
]
},
"require": {
"php": "^7.2.5 || ^8.0",
"phpoption/phpoption": "^1.9.3"
},
"require-dev": {
"phpunit/phpunit": "^8.5.41 || ^9.6.22 || ^10.5.45 || ^11.5.7"
},
"default-branch": true,
"type": "library",
"autoload": {
"psr-4": {
"GrahamCampbell\\ResultType\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Graham Campbell",
"email": "hello@gjcampbell.co.uk",
"homepage": "https://github.com/GrahamCampbell"
}
],
"description": "An Implementation Of The Result Type",
"keywords": [
"Graham Campbell",
"GrahamCampbell",
"Result Type",
"Result-Type",
"result"
],
"support": {
"issues": "https://github.com/GrahamCampbell/Result-Type/issues",
"source": "https://github.com/GrahamCampbell/Result-Type/tree/1.1"
},
"funding": [
{
"url": "https://github.com/GrahamCampbell",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/graham-campbell/result-type",
"type": "tidelift"
}
],
"time": "2025-02-09T22:43:44+00:00"
},
{
"name": "monolog/monolog",
"version": "2.10.0",
@ -170,6 +239,87 @@
},
"time": "2018-02-13T20:26:39+00:00"
},
{
"name": "phpoption/phpoption",
"version": "1.9.3",
"source": {
"type": "git",
"url": "https://github.com/schmittjoh/php-option.git",
"reference": "e3fac8b24f56113f7cb96af14958c0dd16330f54"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/schmittjoh/php-option/zipball/e3fac8b24f56113f7cb96af14958c0dd16330f54",
"reference": "e3fac8b24f56113f7cb96af14958c0dd16330f54",
"shasum": "",
"mirrors": [
{
"url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%",
"preferred": true
}
]
},
"require": {
"php": "^7.2.5 || ^8.0"
},
"require-dev": {
"bamarni/composer-bin-plugin": "^1.8.2",
"phpunit/phpunit": "^8.5.39 || ^9.6.20 || ^10.5.28"
},
"type": "library",
"extra": {
"bamarni-bin": {
"bin-links": true,
"forward-command": false
},
"branch-alias": {
"dev-master": "1.9-dev"
}
},
"autoload": {
"psr-4": {
"PhpOption\\": "src/PhpOption/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"Apache-2.0"
],
"authors": [
{
"name": "Johannes M. Schmitt",
"email": "schmittjoh@gmail.com",
"homepage": "https://github.com/schmittjoh"
},
{
"name": "Graham Campbell",
"email": "hello@gjcampbell.co.uk",
"homepage": "https://github.com/GrahamCampbell"
}
],
"description": "Option Type for PHP",
"keywords": [
"language",
"option",
"php",
"type"
],
"support": {
"issues": "https://github.com/schmittjoh/php-option/issues",
"source": "https://github.com/schmittjoh/php-option/tree/1.9.3"
},
"funding": [
{
"url": "https://github.com/GrahamCampbell",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/phpoption/phpoption",
"type": "tidelift"
}
],
"time": "2024-07-20T21:41:07+00:00"
},
{
"name": "psr/container",
"version": "2.0.2",
@ -285,6 +435,673 @@
},
"time": "2024-08-21T13:31:24+00:00"
},
{
"name": "psr/simple-cache",
"version": "3.0.0",
"source": {
"type": "git",
"url": "https://github.com/php-fig/simple-cache.git",
"reference": "764e0b3939f5ca87cb904f570ef9be2d78a07865"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/php-fig/simple-cache/zipball/764e0b3939f5ca87cb904f570ef9be2d78a07865",
"reference": "764e0b3939f5ca87cb904f570ef9be2d78a07865",
"shasum": "",
"mirrors": [
{
"url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%",
"preferred": true
}
]
},
"require": {
"php": ">=8.0.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "3.0.x-dev"
}
},
"autoload": {
"psr-4": {
"Psr\\SimpleCache\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "PHP-FIG",
"homepage": "https://www.php-fig.org/"
}
],
"description": "Common interfaces for simple caching",
"keywords": [
"cache",
"caching",
"psr",
"psr-16",
"simple-cache"
],
"support": {
"source": "https://github.com/php-fig/simple-cache/tree/3.0.0"
},
"time": "2021-10-29T13:26:27+00:00"
},
{
"name": "symfony/polyfill-ctype",
"version": "v1.31.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-ctype.git",
"reference": "a3cc8b044a6ea513310cbd48ef7333b384945638"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/a3cc8b044a6ea513310cbd48ef7333b384945638",
"reference": "a3cc8b044a6ea513310cbd48ef7333b384945638",
"shasum": "",
"mirrors": [
{
"url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%",
"preferred": true
}
]
},
"require": {
"php": ">=7.2"
},
"provide": {
"ext-ctype": "*"
},
"suggest": {
"ext-ctype": "For best performance"
},
"type": "library",
"extra": {
"thanks": {
"url": "https://github.com/symfony/polyfill",
"name": "symfony/polyfill"
}
},
"autoload": {
"files": [
"bootstrap.php"
],
"psr-4": {
"Symfony\\Polyfill\\Ctype\\": ""
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Gert de Pagter",
"email": "BackEndTea@gmail.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "Symfony polyfill for ctype functions",
"homepage": "https://symfony.com",
"keywords": [
"compatibility",
"ctype",
"polyfill",
"portable"
],
"support": {
"source": "https://github.com/symfony/polyfill-ctype/tree/v1.31.0"
},
"funding": [
{
"url": "https://symfony.com/sponsor",
"type": "custom"
},
{
"url": "https://github.com/fabpot",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
"time": "2024-09-09T11:45:10+00:00"
},
{
"name": "symfony/polyfill-mbstring",
"version": "v1.31.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-mbstring.git",
"reference": "85181ba99b2345b0ef10ce42ecac37612d9fd341"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/85181ba99b2345b0ef10ce42ecac37612d9fd341",
"reference": "85181ba99b2345b0ef10ce42ecac37612d9fd341",
"shasum": "",
"mirrors": [
{
"url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%",
"preferred": true
}
]
},
"require": {
"php": ">=7.2"
},
"provide": {
"ext-mbstring": "*"
},
"suggest": {
"ext-mbstring": "For best performance"
},
"type": "library",
"extra": {
"thanks": {
"name": "symfony/polyfill",
"url": "https://github.com/symfony/polyfill"
}
},
"autoload": {
"files": [
"bootstrap.php"
],
"psr-4": {
"Symfony\\Polyfill\\Mbstring\\": ""
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Nicolas Grekas",
"email": "p@tchwork.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "Symfony polyfill for the Mbstring extension",
"homepage": "https://symfony.com",
"keywords": [
"compatibility",
"mbstring",
"polyfill",
"portable",
"shim"
],
"support": {
"source": "https://github.com/symfony/polyfill-mbstring/tree/v1.31.0"
},
"funding": [
{
"url": "https://symfony.com/sponsor",
"type": "custom"
},
{
"url": "https://github.com/fabpot",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
"time": "2024-09-09T11:45:10+00:00"
},
{
"name": "symfony/polyfill-php80",
"version": "v1.31.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-php80.git",
"reference": "60328e362d4c2c802a54fcbf04f9d3fb892b4cf8"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/60328e362d4c2c802a54fcbf04f9d3fb892b4cf8",
"reference": "60328e362d4c2c802a54fcbf04f9d3fb892b4cf8",
"shasum": "",
"mirrors": [
{
"url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%",
"preferred": true
}
]
},
"require": {
"php": ">=7.2"
},
"type": "library",
"extra": {
"thanks": {
"url": "https://github.com/symfony/polyfill",
"name": "symfony/polyfill"
}
},
"autoload": {
"files": [
"bootstrap.php"
],
"psr-4": {
"Symfony\\Polyfill\\Php80\\": ""
},
"classmap": [
"Resources/stubs"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Ion Bazan",
"email": "ion.bazan@gmail.com"
},
{
"name": "Nicolas Grekas",
"email": "p@tchwork.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "Symfony polyfill backporting some PHP 8.0+ features to lower PHP versions",
"homepage": "https://symfony.com",
"keywords": [
"compatibility",
"polyfill",
"portable",
"shim"
],
"support": {
"source": "https://github.com/symfony/polyfill-php80/tree/v1.31.0"
},
"funding": [
{
"url": "https://symfony.com/sponsor",
"type": "custom"
},
{
"url": "https://github.com/fabpot",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
"time": "2024-09-09T11:45:10+00:00"
},
{
"name": "topthink/think-container",
"version": "v3.0.1",
"source": {
"type": "git",
"url": "https://github.com/top-think/think-container.git",
"reference": "a24d442a02fb2a4716de232ff1a4f006c178a370"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/top-think/think-container/zipball/a24d442a02fb2a4716de232ff1a4f006c178a370",
"reference": "a24d442a02fb2a4716de232ff1a4f006c178a370",
"shasum": "",
"mirrors": [
{
"url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%",
"preferred": true
}
]
},
"require": {
"php": ">=8.0",
"psr/container": "^2.0",
"topthink/think-helper": "^3.1"
},
"require-dev": {
"phpunit/phpunit": "^9.5"
},
"type": "library",
"autoload": {
"files": [],
"psr-4": {
"think\\": "src"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"Apache-2.0"
],
"authors": [
{
"name": "liu21st",
"email": "liu21st@gmail.com"
}
],
"description": "PHP Container & Facade Manager",
"support": {
"issues": "https://github.com/top-think/think-container/issues",
"source": "https://github.com/top-think/think-container/tree/v3.0.1"
},
"time": "2025-01-07T08:19:23+00:00"
},
{
"name": "topthink/think-helper",
"version": "v3.1.11",
"source": {
"type": "git",
"url": "https://github.com/top-think/think-helper.git",
"reference": "1d6ada9b9f3130046bf6922fe1bd159c8d88a33c"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/top-think/think-helper/zipball/1d6ada9b9f3130046bf6922fe1bd159c8d88a33c",
"reference": "1d6ada9b9f3130046bf6922fe1bd159c8d88a33c",
"shasum": "",
"mirrors": [
{
"url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%",
"preferred": true
}
]
},
"require": {
"php": ">=7.1.0"
},
"require-dev": {
"phpunit/phpunit": "^9.5"
},
"type": "library",
"autoload": {
"files": [
"src/helper.php"
],
"psr-4": {
"think\\": "src"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"Apache-2.0"
],
"authors": [
{
"name": "yunwuxin",
"email": "448901948@qq.com"
}
],
"description": "The ThinkPHP6 Helper Package",
"support": {
"issues": "https://github.com/top-think/think-helper/issues",
"source": "https://github.com/top-think/think-helper/tree/v3.1.11"
},
"time": "2025-04-07T06:55:59+00:00"
},
{
"name": "topthink/think-orm",
"version": "v4.0.40",
"source": {
"type": "git",
"url": "https://github.com/top-think/think-orm.git",
"reference": "1637860ff736859058f0a5003c7cc719c2068dbc"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/top-think/think-orm/zipball/1637860ff736859058f0a5003c7cc719c2068dbc",
"reference": "1637860ff736859058f0a5003c7cc719c2068dbc",
"shasum": "",
"mirrors": [
{
"url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%",
"preferred": true
}
]
},
"require": {
"ext-json": "*",
"ext-pdo": "*",
"php": ">=8.0.0",
"psr/log": ">=1.0",
"psr/simple-cache": ">=1.0",
"topthink/think-helper": "^3.1",
"topthink/think-validate": "^3.0"
},
"require-dev": {
"phpunit/phpunit": "^9.6|^10"
},
"suggest": {
"ext-mongodb": "provide mongodb support"
},
"type": "library",
"autoload": {
"files": [
"src/helper.php",
"stubs/load_stubs.php"
],
"psr-4": {
"think\\": "src"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"Apache-2.0"
],
"authors": [
{
"name": "liu21st",
"email": "liu21st@gmail.com"
}
],
"description": "the PHP Database&ORM Framework",
"keywords": [
"database",
"orm"
],
"support": {
"issues": "https://github.com/top-think/think-orm/issues",
"source": "https://github.com/top-think/think-orm/tree/v4.0.40"
},
"time": "2025-05-27T03:32:05+00:00"
},
{
"name": "topthink/think-validate",
"version": "v3.0.7",
"source": {
"type": "git",
"url": "https://github.com/top-think/think-validate.git",
"reference": "85063f6d4ef8ed122f17a36179dc3e0949b30988"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/top-think/think-validate/zipball/85063f6d4ef8ed122f17a36179dc3e0949b30988",
"reference": "85063f6d4ef8ed122f17a36179dc3e0949b30988",
"shasum": "",
"mirrors": [
{
"url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%",
"preferred": true
}
]
},
"require": {
"php": ">=8.0",
"topthink/think-container": ">=3.0"
},
"type": "library",
"autoload": {
"files": [
"src/helper.php"
],
"psr-4": {
"think\\": "src"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"Apache-2.0"
],
"authors": [
{
"name": "liu21st",
"email": "liu21st@gmail.com"
}
],
"description": "think validate",
"support": {
"issues": "https://github.com/top-think/think-validate/issues",
"source": "https://github.com/top-think/think-validate/tree/v3.0.7"
},
"time": "2025-06-11T05:51:40+00:00"
},
{
"name": "vlucas/phpdotenv",
"version": "v5.6.1",
"source": {
"type": "git",
"url": "https://github.com/vlucas/phpdotenv.git",
"reference": "a59a13791077fe3d44f90e7133eb68e7d22eaff2"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/vlucas/phpdotenv/zipball/a59a13791077fe3d44f90e7133eb68e7d22eaff2",
"reference": "a59a13791077fe3d44f90e7133eb68e7d22eaff2",
"shasum": "",
"mirrors": [
{
"url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%",
"preferred": true
}
]
},
"require": {
"ext-pcre": "*",
"graham-campbell/result-type": "^1.1.3",
"php": "^7.2.5 || ^8.0",
"phpoption/phpoption": "^1.9.3",
"symfony/polyfill-ctype": "^1.24",
"symfony/polyfill-mbstring": "^1.24",
"symfony/polyfill-php80": "^1.24"
},
"require-dev": {
"bamarni/composer-bin-plugin": "^1.8.2",
"ext-filter": "*",
"phpunit/phpunit": "^8.5.34 || ^9.6.13 || ^10.4.2"
},
"suggest": {
"ext-filter": "Required to use the boolean validator."
},
"type": "library",
"extra": {
"bamarni-bin": {
"bin-links": true,
"forward-command": false
},
"branch-alias": {
"dev-master": "5.6-dev"
}
},
"autoload": {
"psr-4": {
"Dotenv\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Graham Campbell",
"email": "hello@gjcampbell.co.uk",
"homepage": "https://github.com/GrahamCampbell"
},
{
"name": "Vance Lucas",
"email": "vance@vancelucas.com",
"homepage": "https://github.com/vlucas"
}
],
"description": "Loads environment variables from `.env` to `getenv()`, `$_ENV` and `$_SERVER` automagically.",
"keywords": [
"dotenv",
"env",
"environment"
],
"support": {
"issues": "https://github.com/vlucas/phpdotenv/issues",
"source": "https://github.com/vlucas/phpdotenv/tree/v5.6.1"
},
"funding": [
{
"url": "https://github.com/GrahamCampbell",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/vlucas/phpdotenv",
"type": "tidelift"
}
],
"time": "2024-07-20T21:52:34+00:00"
},
{
"name": "webman/think-orm",
"version": "v2.1.6",
"source": {
"type": "git",
"url": "https://github.com/webman-php/think-orm.git",
"reference": "af4a2586177a333983e0da1bf6512ec12f894b29"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/webman-php/think-orm/zipball/af4a2586177a333983e0da1bf6512ec12f894b29",
"reference": "af4a2586177a333983e0da1bf6512ec12f894b29",
"shasum": "",
"mirrors": [
{
"url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%",
"preferred": true
}
]
},
"require": {
"php": ">=8.1",
"topthink/think-container": "^2.0|^3.0",
"topthink/think-orm": "^2.0.53 || ^3.0.0 || ^4.0.30 || dev-master",
"workerman/webman-framework": "^2.1 || dev-master"
},
"type": "library",
"autoload": {
"psr-4": {
"support\\": "src/support",
"Webman\\ThinkOrm\\": "src"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"support": {
"issues": "https://github.com/webman-php/think-orm/issues",
"source": "https://github.com/webman-php/think-orm/tree/v2.1.6"
},
"time": "2025-05-27T13:15:25+00:00"
},
{
"name": "workerman/coroutine",
"version": "v1.1.3",

View File

@ -14,4 +14,5 @@
return [
support\bootstrap\Session::class,
Webman\ThinkOrm\ThinkOrm::class,
];

284
config/think-orm.php Normal file
View File

@ -0,0 +1,284 @@
<?php
return [
'default' => 'duanju_master',
'connections' => [
'duanju_master' => [
// 数据库类型
'type' => 'mysql',
// 服务器地址
'hostname' => env('HOSTNAME', '127.0.0.1'),
// 数据库名
'database' => 'duanju',
// 数据库用户名
'username' => env('USERNAME', 'video_user'),
// 数据库密码
'password' => env('PASSWORD', 'VideoUser@1'),
// 数据库连接端口
'hostport' => env('HOSTPORT', '3306'),
// 数据库连接参数
'params' => [
// 连接超时3秒
\PDO::ATTR_TIMEOUT => 3,
],
// 数据库编码默认采用utf8
'charset' => 'utf8mb4',
// 数据库表前缀
'prefix' => '',
// 断线重连
'break_reconnect' => true,
// 自定义分页类
'bootstrap' => '',
// 连接池配置
'pool' => [
'max_connections' => 500, // 最大连接数
'min_connections' => 20, // 最小连接数
'wait_timeout' => 3, // 从连接池获取连接等待超时时间
'idle_timeout' => 60, // 连接最大空闲时间,超过该时间会被回收
'heartbeat_interval' => 50, // 心跳检测间隔需要小于60秒
],
],
'duanju_slave' => [
// 数据库类型
'type' => 'mysql',
// 服务器地址
'hostname' => env('SLAVE_HOSTNAME', '127.0.0.1'),
// 数据库名
'database' => 'duanju',
// 数据库用户名
'username' => env('SLAVE_USERNAME', 'video_user'),
// 数据库密码
'password' => env('SLAVE_PASSWORD', 'VideoUser@1'),
// 数据库连接端口
'hostport' => env('SLAVE_HOSTPORT', '3306'),
// 数据库连接参数
'params' => [
// 连接超时3秒
\PDO::ATTR_TIMEOUT => 3,
],
// 数据库编码默认采用utf8
'charset' => 'utf8mb4',
// 数据库表前缀
'prefix' => '',
// 断线重连
'break_reconnect' => true,
// 自定义分页类
'bootstrap' => '',
// 连接池配置
'pool' => [
'max_connections' => 500, // 最大连接数
'min_connections' => 20, // 最小连接数
'wait_timeout' => 3, // 从连接池获取连接等待超时时间
'idle_timeout' => 60, // 连接最大空闲时间,超过该时间会被回收
'heartbeat_interval' => 50, // 心跳检测间隔需要小于60秒
],
],
'duanju_slave_0' => [
// 数据库类型
'type' => 'mysql',
// 服务器地址
'hostname' => env('SLAVE_HOSTNAME', '127.0.0.1'),
// 数据库名
'database' => 'duanju-0',
// 数据库用户名
'username' => env('SLAVE_USERNAME', 'video_user'),
// 数据库密码
'password' => env('SLAVE_PASSWORD', 'VideoUser@1'),
// 数据库连接端口
'hostport' => env('SLAVE_HOSTPORT', '3306'),
// 数据库连接参数
'params' => [
// 连接超时3秒
\PDO::ATTR_TIMEOUT => 3,
],
// 数据库编码默认采用utf8
'charset' => 'utf8mb4',
// 数据库表前缀
'prefix' => '',
// 断线重连
'break_reconnect' => true,
// 自定义分页类
'bootstrap' => '',
// 连接池配置
'pool' => [
'max_connections' => 500, // 最大连接数
'min_connections' => 20, // 最小连接数
'wait_timeout' => 3, // 从连接池获取连接等待超时时间
'idle_timeout' => 60, // 连接最大空闲时间,超过该时间会被回收
'heartbeat_interval' => 50, // 心跳检测间隔需要小于60秒
],
],
'duanju_slave_1' => [
// 数据库类型
'type' => 'mysql',
// 服务器地址
'hostname' => env('SLAVE_HOSTNAME', '127.0.0.1'),
// 数据库名
'database' => 'duanju-1',
// 数据库用户名
'username' => env('SLAVE_USERNAME', 'video_user'),
// 数据库密码
'password' => env('SLAVE_PASSWORD', 'VideoUser@1'),
// 数据库连接端口
'hostport' => env('SLAVE_HOSTPORT', '3306'),
// 数据库连接参数
'params' => [
// 连接超时3秒
\PDO::ATTR_TIMEOUT => 3,
],
// 数据库编码默认采用utf8
'charset' => 'utf8mb4',
// 数据库表前缀
'prefix' => '',
// 断线重连
'break_reconnect' => true,
// 自定义分页类
'bootstrap' => '',
// 连接池配置
'pool' => [
'max_connections' => 500, // 最大连接数
'min_connections' => 20, // 最小连接数
'wait_timeout' => 3, // 从连接池获取连接等待超时时间
'idle_timeout' => 60, // 连接最大空闲时间,超过该时间会被回收
'heartbeat_interval' => 50, // 心跳检测间隔需要小于60秒
],
],
'duanju_slave_2' => [
// 数据库类型
'type' => 'mysql',
// 服务器地址
'hostname' => env('SLAVE_HOSTNAME', '127.0.0.1'),
// 数据库名
'database' => 'duanju-2',
// 数据库用户名
'username' => env('SLAVE_USERNAME', 'video_user'),
// 数据库密码
'password' => env('SLAVE_PASSWORD', 'VideoUser@1'),
// 数据库连接端口
'hostport' => env('SLAVE_HOSTPORT', '3306'),
// 数据库连接参数
'params' => [
// 连接超时3秒
\PDO::ATTR_TIMEOUT => 3,
],
// 数据库编码默认采用utf8
'charset' => 'utf8mb4',
// 数据库表前缀
'prefix' => '',
// 断线重连
'break_reconnect' => true,
// 自定义分页类
'bootstrap' => '',
// 连接池配置
'pool' => [
'max_connections' => 500, // 最大连接数
'min_connections' => 20, // 最小连接数
'wait_timeout' => 3, // 从连接池获取连接等待超时时间
'idle_timeout' => 60, // 连接最大空闲时间,超过该时间会被回收
'heartbeat_interval' => 50, // 心跳检测间隔需要小于60秒
],
],
'duanju_slave_3' => [
// 数据库类型
'type' => 'mysql',
// 服务器地址
'hostname' => env('SLAVE_HOSTNAME', '127.0.0.1'),
// 数据库名
'database' => 'duanju-3',
// 数据库用户名
'username' => env('SLAVE_USERNAME', 'video_user'),
// 数据库密码
'password' => env('SLAVE_PASSWORD', 'VideoUser@1'),
// 数据库连接端口
'hostport' => env('SLAVE_HOSTPORT', '3306'),
// 数据库连接参数
'params' => [
// 连接超时3秒
\PDO::ATTR_TIMEOUT => 3,
],
// 数据库编码默认采用utf8
'charset' => 'utf8mb4',
// 数据库表前缀
'prefix' => '',
// 断线重连
'break_reconnect' => true,
// 自定义分页类
'bootstrap' => '',
// 连接池配置
'pool' => [
'max_connections' => 500, // 最大连接数
'min_connections' => 20, // 最小连接数
'wait_timeout' => 3, // 从连接池获取连接等待超时时间
'idle_timeout' => 60, // 连接最大空闲时间,超过该时间会被回收
'heartbeat_interval' => 50, // 心跳检测间隔需要小于60秒
],
],
'duanju_slave_4' => [
// 数据库类型
'type' => 'mysql',
// 服务器地址
'hostname' => env('SLAVE_HOSTNAME', '127.0.0.1'),
// 数据库名
'database' => 'duanju-4',
// 数据库用户名
'username' => env('SLAVE_USERNAME', 'video_user'),
// 数据库密码
'password' => env('SLAVE_PASSWORD', 'VideoUser@1'),
// 数据库连接端口
'hostport' => env('SLAVE_HOSTPORT', '3306'),
// 数据库连接参数
'params' => [
// 连接超时3秒
\PDO::ATTR_TIMEOUT => 3,
],
// 数据库编码默认采用utf8
'charset' => 'utf8mb4',
// 数据库表前缀
'prefix' => '',
// 断线重连
'break_reconnect' => true,
// 自定义分页类
'bootstrap' => '',
// 连接池配置
'pool' => [
'max_connections' => 500, // 最大连接数
'min_connections' => 20, // 最小连接数
'wait_timeout' => 3, // 从连接池获取连接等待超时时间
'idle_timeout' => 60, // 连接最大空闲时间,超过该时间会被回收
'heartbeat_interval' => 50, // 心跳检测间隔需要小于60秒
],
],
],
'db_map' => [
'duanju_slave', 'duanju_slave_0', 'duanju_slave_1', 'duanju_slave_2', 'duanju_slave_3', 'duanju_slave_4',
],
// 从主库
'search_library' => 'duanju_slave',
'z_library' => 'duanju_master',
// 主主库
// 数据库路由配置
'route' => [
// user_id分库的表
'user_money_details' => ['master' => 'duanju_master', 'slave' => 'duanju_slave_{$user_id%5}'],
'sys_user_money_details' => ['master' => 'duanju_master', 'slave' => 'duanju_slave_{$user_id%5}'],
'orders' => ['master' => 'duanju_master', 'slave' => 'duanju_slave_{$user_id%5}'],
'course_collect' => ['master' => 'duanju_master', 'slave' => 'duanju_slave_{$user_id%5}'],
'pay_details' => ['master' => 'duanju_master', 'slave' => 'duanju_slave_{$user_id%5}'],
'disc_spinning_record' => ['master' => 'duanju_master', 'slave' => 'duanju_slave_{$user_id%5}'],
'cash_out' => ['master' => 'duanju_master', 'slave' => 'duanju_slave_{$user_id%5}'],
'course_user' => ['master' => 'duanju_master', 'slave' => 'duanju_slave_{$user_id%5}'],
'tb_user' => ['master' => 'duanju_master', 'slave' => 'duanju_slave_{$user_id%5}'],
'task_center_record' => ['master' => 'duanju_master', 'slave' => 'duanju_slave_{$user_id%5}'],
'user_money' => ['master' => 'duanju_master', 'slave' => 'duanju_slave_{$user_id%5}'],
'user_sign_record' => ['master' => 'duanju_master', 'slave' => 'duanju_slave_{$user_id%5}'],
'invite_achievement' => ['master' => 'duanju_master', 'slave' => 'duanju_slave_{$user_id%5}'],
'invite_money' => ['master' => 'duanju_master', 'slave' => 'duanju_slave_{$user_id%5}'],
'user_info' => ['master' => 'duanju_master', 'slave' => 'duanju_slave_{$user_id%5}'],
'sys_user' => ['master' => 'duanju_master', 'slave' => 'duanju_slave_{$user_id%5}'],
// course_id分库的表
'course_details' => ['master' => 'duanju_master', 'slave' => 'duanju_slave_{$course_id%5}'],
],
];