// +---------------------------------------------------------------------- declare (strict_types = 1); namespace addon\articles; use addon\articles\library\ArticleSchema; use think\facade\Db; use ywxapp\AddonBase; use ywxapp\service\AddonService; /** * 文章CMS插件启动类 */ class Addon extends AddonBase { /** 插件私有表(不含表前缀) */ private const TABLES = [ 'articles_article', 'articles_article_tag', 'articles_category', 'articles_tag', 'articles_comment', ]; // 插件基本信息(版本号须与 info.php 保持一致) public $info = [ 'name' => 'articles', 'title' => '文章CMS', 'description' => '完整文章类 CMS 插件:文章、分类、标签、评论', 'status' => 1, 'author' => 'ywxapp', 'version' => '1.0.1', 'type' => 1, ]; // 插件安装 public function install() { // install.sql 由框架导入(白名单仅 CREATE TABLE / INSERT); // 这里再兜底一次,确保表齐备且不缺列。 ArticleSchema::repair(); return true; } // 插件卸载 public function uninstall() { $prefix = $this->prefix(); foreach (self::TABLES as $table) { try { // 用配置前缀拼接,勿硬编码 wxapp_ Db::execute("DROP TABLE IF EXISTS `{$prefix}{$table}`"); } catch (\Throwable $e) { // 单表删除失败不阻断整体卸载 } } // 菜单由框架 deleteMenu() 清理;这里补清「配置残留」 // (框架卸载默认不清配置,重装会继承旧值) try { Db::name('common_addonconf')->where('addon', 'articles')->delete(); } catch (\Throwable $e) { // 表不存在时忽略 } AddonService::clearConfigCache('articles'); // 清理静态资源:框架卸载只删 public/static/addon//, // 而本插件资源实际在 public/static/articles/,需自行清理。 $this->deleteDirectory(public_path() . 'static' . DIRECTORY_SEPARATOR . 'articles'); return true; } // 插件启用 public function enable() { // 启用时做一次轻量建表兜底(不补列,避免线上长耗时) ArticleSchema::repair(false); return true; } // 插件禁用 public function disable() { return true; } /** * 插件升级(覆盖升级 / addon:manage 时由框架回调) * * 注意:install.sql 的 ALTER 会被 importsql 白名单跳过, * 因此「老库补列 + 补索引」必须放在这里(ArticleSchema::repair)。 * * @param string $currentVersion 已安装版本号 */ public function upgrade($currentVersion = '') { ArticleSchema::repair(); return true; } /** * 递归删除目录(卸载时清理静态资源) */ private function deleteDirectory(string $dir): void { if (!is_dir($dir)) { return; } $items = scandir($dir); if (!is_array($items)) { return; } foreach ($items as $item) { if ($item === '.' || $item === '..') { continue; } $path = $dir . DIRECTORY_SEPARATOR . $item; if (is_dir($path)) { $this->deleteDirectory($path); } else { @unlink($path); } } @rmdir($dir); } /** * 当前数据库表前缀 */ private function prefix(): string { $default = (string) config('database.default', 'mysql'); return (string) config("database.connections.{$default}.prefix", ''); } }