[列 => 列定义]] */ private const COLUMNS = [ 'paycenter_trade' => [ 'biz' => '`biz` varchar(30) NOT NULL DEFAULT \'\' COMMENT \'业务标识\'', 'biz_id' => '`biz_id` int NOT NULL DEFAULT 0 COMMENT \'业务侧订单主键\'', 'scene' => '`scene` varchar(20) NOT NULL DEFAULT \'\' COMMENT \'支付场景\'', 'attach' => '`attach` varchar(500) NOT NULL DEFAULT \'\' COMMENT \'业务附加数据\'', 'notify_at' => '`notify_at` int NOT NULL DEFAULT 0 COMMENT \'回调时间\'', ], ]; private static bool $done = false; /** install.sql 解析缓存:[不含前缀表名 => CREATE 语句] */ private static array $ddl = []; public static function ensure(): void { if (self::$done) { return; } self::$done = true; $prefix = self::prefix(); foreach (self::ddl() as $table => $statement) { $full = $prefix . $table; if (self::tableExists($full)) { continue; } try { Db::execute(str_replace('__PREFIX__', $prefix, $statement)); } catch (\Throwable $e) { // 建表失败不阻断业务:后续写库会再暴露真实错误 trace('[paycenter] 建表失败 ' . $full . ':' . $e->getMessage(), 'error'); } } foreach (self::COLUMNS as $table => $columns) { $full = $prefix . $table; if (!self::tableExists($full)) { continue; } foreach ($columns as $col => $def) { try { if (empty(Db::query("SHOW COLUMNS FROM `{$full}` LIKE '{$col}'"))) { Db::execute("ALTER TABLE `{$full}` ADD COLUMN {$def}"); } } catch (\Throwable) { // 补列失败不阻断 } } } } public static function prefix(): string { $default = (string) config('database.default', 'mysql'); return (string) config("database.connections.{$default}.prefix", ''); } private static function tableExists(string $full): bool { try { return !empty(Db::query("SHOW TABLES LIKE '{$full}'")); } catch (\Throwable) { return false; } } /** * 解析插件自带 install.sql,取出建表语句。 * @return array */ private static function ddl(): array { if (self::$ddl !== []) { return self::$ddl; } $file = dirname(__DIR__) . DIRECTORY_SEPARATOR . 'install.sql'; if (!is_file($file)) { return self::$ddl = []; } $sql = (string) file_get_contents($file); if (preg_match_all('/CREATE\s+TABLE\s+IF\s+NOT\s+EXISTS\s+`?__PREFIX__(\w+)`?\s*\(.*?\)\s*[^;]*;/is', $sql, $m)) { foreach ($m[1] as $i => $table) { self::$ddl[$table] = $m[0][$i]; } } return self::$ddl; } }