// +---------------------------------------------------------------------- namespace ywxapp\model; use think\facade\Log; /** * 插件配置表模型({prefix}common_addonconf) * * 表结构:每个配置项独立成行,addon + name 唯一。 * * 背景:该表原先只有 AddonService 中的裸 Db::name('common_addonconf') 访问, * 既无模型,也未被 public/install/install.sql 收录 —— 这意味着 BaseModel 的 * 通用自愈(从 install.sql 还原)对它无效,表一旦缺失,插件配置读写会直接 1146。 * 因此本模型内聚了建表 DDL 作为该表的兜底事实源。 * * @author ywxapp */ class CommonAddonconf extends BaseModel { /** * 建表语句(install.sql 未收录该表,故在此自带;__PREFIX__ 运行时替换为实际前缀) */ private const TABLE_DDL = <<<'SQL' CREATE TABLE IF NOT EXISTS `__PREFIX__common_addonconf` ( `id` int unsigned NOT NULL AUTO_INCREMENT, `addon` varchar(50) NOT NULL DEFAULT '' COMMENT '插件标识', `name` varchar(50) NOT NULL DEFAULT '' COMMENT '配置项名', `value` text COMMENT '配置值', `create_at` int unsigned NOT NULL DEFAULT '0', `update_at` int unsigned NOT NULL DEFAULT '0', PRIMARY KEY (`id`), UNIQUE KEY `uk_addon_name` (`addon`,`name`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='插件配置表' SQL; protected function getOptions(): array { return [ 'strict' => false, 'autoWriteTimestamp' => 'int', 'createTime' => 'create_at', 'updateTime' => 'update_at', 'readonly' => ['id'], ]; } /** * 运行时自愈:确保 common_addonconf 表存在。 * 优先 install.sql(将来若补录则以事实源为准),缺失则用本类内置 DDL。 */ public static function ensureSchema(): void { $prefix = BaseModel::currentPrefix(); BaseModel::ensureTableFromInstall($prefix, 'common_addonconf'); $table = $prefix . 'common_addonconf'; if (! BaseModel::tableExists($table)) { BaseModel::ensureTable($table, str_replace('__PREFIX__', $prefix, self::TABLE_DDL)); } } /** * 提前自愈:common_addonconf 不在 install.sql 中,必须在 think-orm 读取表结构 * (parent::__construct 内会触发 getTableInfo)之前先把表补上,否则报 1146。 */ public function __construct(array $data = []) { self::ensureSchema(); parent::__construct($data); } protected function initialize() { parent::initialize(); self::ensureSchema(); } /** * 读取某插件的全部配置(addon => [name => value]) * * 兜底:表缺失且自愈失败(如无 CREATE 权限)时返回空数组并记录日志, * 避免 1146 直接冒泡成后台不可用。 */ public static function getAddonConfig(string $addon): array { try { self::ensureSchema(); return self::where('addon', $addon)->column('value', 'name'); } catch (\Throwable $e) { try { Log::error('[CommonAddonconf] 读取插件配置失败: ' . $addon . ' - ' . $e->getMessage()); } catch (\Throwable $e2) { // 日志不可用时彻底静默 } return []; } } /** * 写入/更新某插件的单个配置项(同兜底策略,失败返回 false) */ public static function setAddonConfig(string $addon, string $name, $value): bool { try { self::ensureSchema(); $row = self::where('addon', $addon)->where('name', $name)->find(); if ($row) { $row->value = $value; $row->save(); return true; } self::create([ 'addon' => $addon, 'name' => $name, 'value' => $value, ]); return true; } catch (\Throwable $e) { try { Log::error("[CommonAddonconf] 写入插件配置失败: {$addon}.{$name} - " . $e->getMessage()); } catch (\Throwable $e2) { // 忽略 } return false; } } }