| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278 |
- <?php
- // +----------------------------------------------------------------------
- // | likeadmin快速开发前后端分离管理后台(PHP版)
- // +----------------------------------------------------------------------
- // | 欢迎阅读学习系统程序代码,建议反馈是我们前进的动力
- // | 开源版本可自由商用,可去除界面版权logo
- // | gitee下载:https://gitee.com/likeshop_gitee/likeadmin
- // | github下载:https://github.com/likeshop-github/likeadmin
- // | 访问官网:https://www.likeadmin.cn
- // | likeadmin团队 版权所有 拥有最终解释权
- // +----------------------------------------------------------------------
- // | author: likeadminTeam
- // +----------------------------------------------------------------------
- namespace app\adminapi\service;
- use Exception;
- use PDO;
- use PDOException;
- use think\facade\Config;
- /**
- * 创建租户service
- * Class TenantCreatService
- * @package app\adminapi\service
- */
- class TenantCreatService
- {
- /**
- * 数据库连接
- */
- private $dbh = null;
- /**
- * @notes 创建租户模式分表
- * @param $tenantSn
- * @return bool
- * @throws \Random\RandomException
- * @author yfdong
- * @date 2024/09/28 10:55
- */
- public function createTenantTable($tenantSn)
- {
- // 创建数据库链接
- $this->dbh = self::connectDB();
- // 获取数据库版本
- $version = self::getMysqlVersion($this->dbh);
- // 获取数据库SQL文件路径
- $dbFile = dirname(__DIR__) . '/db/tenant.sql';
- // 检查文件是否存在,若不存在,直接返回错误
- if (!file_exists($dbFile)) {
- throw new Exception("SQL file not found: $dbFile");
- }
- // 读取并规范化SQL文件内容
- $content = str_replace(";\r\n", ";\n", file_get_contents($dbFile));
- // 对数据库中的脚本进行租户唯一标识替换
- $content = str_replace("{tenantSn}", $tenantSn, $content);
- // 分割SQL语句
- $tables = explode(";\n", $content);
- // 初始化安装时间戳
- $installTime = microtime(true) * 10000;
- // 循环处理每个SQL语句
- foreach ($tables as $table) {
- // 去除前后空白字符
- $table = trim($table);
- // 跳过空的SQL语句
- if (empty($table)) continue;
- // 处理数据库版本兼容性问题(版本<=4.1时移除CHARSET)
- if (strpos($table, 'CREATE') !== false && $version <= 4.1) {
- $table = str_replace('DEFAULT CHARSET=utf8', '', $table);
- }
- // 跳过注释的SQL语句
- if (strpos($table, '--') === 0) continue;
- // 替换表前缀
- $table = str_replace('`la_', env('database.database', 'likeadmin_saas') . '.`la_', $table);
- $table = str_replace('`la_', '`' . env('database.prefix', 'la_'), $table);
- // 如果是创建表的SQL,记录表名和时间戳
- // if (strpos($table, 'CREATE') !== false) {
- // $tableName = explode('`', $table)[1];
- // $installTime += random_int(3000, 7000); // 随机递增安装时间
- // $successTable[] = [$tableName, date('Y-m-d H:i:s', $installTime / 10000)];
- // }
- // 执行SQL语句
- try {
- if (!$this->dbh->query($table)) {
- throw new Exception("SQL execution failed: $table");
- }
- } catch (Exception $e) {
- // 捕获异常并输出详细错误信息
- echo 'Error executing SQL: ' . htmlspecialchars($table) . "<br>";
- echo 'Error message: ' . $e->getMessage() . "<br>";
- return false;
- }
- }
- return true;
- }
- /**
- * @notes 初始化租户数据
- * @param $tenantSn
- * @return bool
- * @throws \Random\RandomException
- * @author yfdong
- * @date 2024/10/01 15:43
- */
- public function initializationTenantData($tenantId, $tenantSn, $param)
- {
- // 创建数据库链接
- $this->dbh = self::connectDB();
- // 获取数据库版本
- $version = self::getMysqlVersion($this->dbh);
- // 获取数据库SQL文件路径
- $dbFile = dirname(__DIR__) . '/db/tenantData.sql';
- // 检查文件是否存在,若不存在,直接返回错误
- if (!file_exists($dbFile)) {
- throw new Exception("SQL file not found: $dbFile");
- }
- // 读取并规范化SQL文件内容
- $content = str_replace(";\r\n", ";\n", file_get_contents($dbFile));
- // 对数据库中的脚本进行租户唯一标识替换
- $content = str_replace("{tenantSn}", $tenantSn, $content);
- // 对数据库中的脚本进行租户唯一标识替换
- $content = str_replace("{tenantId}", $tenantId, $content);
- // 分割SQL语句
- $tables = explode(";\n", $content);
- // 初始化安装时间戳
- $installTime = microtime(true) * 10000;
- // 创建管理员账号
- $tables[] = $this->initAccount($tenantId, $tenantSn, $param);
- // 循环处理每个SQL语句
- foreach ($tables as $table) {
- // 去除前后空白字符
- $table = trim($table);
- // 跳过空的SQL语句
- if (empty($table)) continue;
- // 处理数据库版本兼容性问题(版本<=4.1时移除CHARSET)
- if (strpos($table, 'CREATE') !== false && $version <= 4.1) {
- $table = str_replace('DEFAULT CHARSET=utf8', '', $table);
- }
- // 跳过注释的SQL语句
- if (strpos($table, '--') === 0) continue;
- // 替换表前缀
- $table = str_replace('`la_', env('database.database', 'likeadmin_saas') . '.`la_', $table);
- $table = str_replace('`la_', '`' . env('database.prefix', 'la_'), $table);
- // 执行SQL语句
- try {
- if (!$this->dbh->query($table)) {
- throw new Exception("SQL execution failed: $table");
- }
- } catch (Exception $e) {
- // 捕获异常并输出详细错误信息
- echo "初始化租户初始数据失败";
- echo 'Error executing SQL: ' . htmlspecialchars($table) . "<br>";
- echo 'Error message: ' . $e->getMessage() . "<br>";
- return false;
- }
- }
- return true;
- }
- /**
- * @notes 检查数据库版本
- * @return string
- * @author yfdong
- * @date 2024/10/01 13:39
- */
- public function getMysqlVersion($dbh)
- {
- $sql = "SELECT VERSION() AS version";
- $result = $dbh->query($sql)->fetch();
- return substr($result->version, 0, 3);
- }
- /**
- * @notes 创建数据库链接
- * @return PDO|string
- * @author yfdong
- * @date 2024/10/01 13:39
- */
- public function connectDB()
- {
- // 获取数据库链接
- $host = env('database.hostname', '');
- $port = env('database.hostport', '');
- $user = env('database.username', '');
- $password = env('database.password', '');
- $dsn = "mysql:host={$host}; port={$port}";
- try {
- $this->dbh = new PDO($dsn, $user, $password);
- $this->dbh->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_OBJ);
- $this->dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
- $this->dbh->exec("SET NAMES 'utf8mb4'");
- $this->dbh->exec("SET NAMES 'utf8mb4'");
- try {
- $this->dbh->exec("SET GLOBAL sql_mode='STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION';");
- } catch (Exception $e) {
- }
- return $this->dbh;
- } catch (PDOException $exception) {
- return $exception->getMessage();
- }
- }
- /**
- * @notes 创建管理员账号
- * @param $post
- * @return string
- * @author yfdong
- * @date 2024/10/01 16:02
- */
- public function initAccount($tenantId, $tenantSn, $param)
- {
- $time = time();
- $salt = Config::get('project.unique_identification');
- $defaultPassword = Config::get('project.default_password');
- global $uniqueSalt;
- $uniqueSalt = $salt;
- // 账号
- if (isset($param['account'])) {
- $account = $param['account'];
- } else {
- $account = 'admin';
- }
- //设置密码
- if (isset($param['password'])) {
- $password = md5($salt . md5($param['password'] . $salt));
- } else {
- $password = $defaultPassword;
- }
- // 超级管理员
- $sql = "INSERT INTO `la_tenant_admin_{$tenantSn}`(`id`, `tenant_id`,`root`, `name`, `avatar`, `account`, `password`, `login_time`, `login_ip`, `multipoint_login`, `disable`, `create_time`, `update_time`, `delete_time`) VALUES (1, {$tenantId},1, '超级管理员', '', '{$account}', '{$password}','{$time}', '', 1, 0, '{$time}', '{$time}', NULL);";
- // 超级管理员关联部门
- $sql .= "INSERT INTO `la_tenant_admin_dept_{$tenantSn}` (`admin_id`, `dept_id`) VALUES (1, 1);";
- return $sql;
- }
- }
|