当前位置:首页 > 后端

ThinkOrm4.0分表最佳实践

Z先生4小时前后端3

一、定义模型,并在模型init时自动建表

<?php

namespace database\model\tenant;

use think\facade\Db;
use think\Model;
use think\model\concern\SoftDelete;


class User extends Model {

    use SoftDelete;
    // 模型配置
    protected function getOptions(): array {
        return [
            'name' => 'user',
            // 'suffix' => '_en',
        ];
    }

    protected function init(): void {
        $table_with_suffix = $this->getTable();
        $table_name = $this->getOption('name');
        $table_prefix =  explode($table_name, $table_with_suffix)[0];
        
        // $this->getOption('suffix') 获取不到
        $suffix = '_cn'; // 需要从其他地方传入,init时,动态取不到后缀,没有初始化过来。

        $table_template = $table_prefix . $table_name;
        $table_with_suffix = $table_prefix . $table_name . $suffix;

        $result = Db::query("SHOW TABLES LIKE '{$table_with_suffix}'");
        if (empty($result)) {
            Db::query("create table $table_with_suffix like  $table_template");
        }
        
        $this->setOption('suffix', $suffix);
    }

}

二、集合查询方法,单表查询只需要设置suffix即可

/**
 *
 * 分表查询方法
 *
 * @author  Joe <joe@xcwl.com>
 * @version v1.01
 * @date 2026-07-17
 *
 * @param string $table_name 表名 'user'
 * @param array $suffix 分表后缀,如['en', 'cn']
 * @param array $field 查询字段
 * @param array $where 查询条件
 * @param int $pagesize 分页大小
 * @param int $page 分页页码
 * @param array $order 排序条件
 * @return array 查询结果
 * 
 **/
function queryTable(string $table_name, array $suffix, array $field = ['*'], array $where = [], int $pagesize = 20, int $page = 1, array $order = []) {
    // 查询集合
    $queries = collect();
    //把最原始表单的数据加入
    if ("SHOW TABLES LIKE '{$table_name}'") {
        $queries->push(
            Db::name($table_name)
                // 建议都用field查询字段,SQL尽可能的优化性能
                ->field($field)
                ->where($where)
        );
    }

    foreach ($suffix as $item) {
        // 组装分表
        $table_with_suffix = $table_name . '_' . $item;
        if ("SHOW TABLES LIKE '{$table_with_suffix}'") {
            $queries->push(
                Db::name($table_with_suffix)
                    // 建议都用field查询字段,SQL尽可能的优化性能
                    ->field($field)
                    ->where($where)
            );
        }
    }

    $unionQuery = $queries->shift();
    // 循环剩下的表添加union
    $queries->each(function ($item, $key) use ($unionQuery) {
        $unionQuery->unionAll($item);
    });
    // 把用 unionAll链接起来的sql 组成一个表
    $model = Db::table($table_name)
        // 添加临时表
        ->from(Db::raw("({$unionQuery->fetchSql()}) AS {$table_name}"))
        // 合并查询条件
        ->mergeBindings($unionQuery);
    if ($order) {
        $model->order($order);
    }

    $data['total'] = $model->count();
    $data['data'] = $model->limit($pagesize)->page($page)->select()->toArray();
    return $data;
}


标签: phpthinkorm
分享给朋友:

相关文章

Webman配合ThinkORM4.0自动分库

一、配置数据库链接return [     'default' => 'mysql',&n…

发表评论

访客

◎欢迎参与讨论,请在这里发表您的看法和观点。