// +---------------------------------------------------------------------- if (!function_exists('addon_url')) { /** * 生成插件访问地址(MultiApp 多应用模型:///) * @param string $name 插件标识 * @param string $url 相对路径,如 'admin/index' 或 '/admin/index' * @param array $vars 附加 GET 参数 * @return string */ function addon_url(string $name, string $url = '', array $vars = []): string { $path = '/' . trim($name, '/'); if ($url !== '' && $url !== '/') { $path .= '/' . ltrim($url, '/'); } return $vars ? $path . '?' . http_build_query($vars) : $path; } } if (!function_exists('get_addon_instance')) { /** * 获取插件主类实例(addon\\Addon) * @param string $name 插件标识 * @return object|null */ function get_addon_instance(string $name) { $class = '\\addon\\' . $name . '\\Addon'; if (!class_exists($class)) { return null; } return app($class); } } if (!function_exists('get_addon_info')) { /** * 读取插件信息(优先缓存,force=true 强制重读) * @param string $name 插件标识 * @param bool $force * @return array */ function get_addon_info(string $name = '', bool $force = false): array { $instance = get_addon_instance($name); return $instance ? $instance->getInfo($name, $force) : []; } } if (!function_exists('get_addon_config')) { /** * 读取插件配置(优先缓存,force=true 强制重读) * @param string $name 插件标识 * @param bool $force * @return array */ function get_addon_config(string $name = '', bool $force = false): array { $instance = get_addon_instance($name); return $instance ? $instance->getConfig($name, $force) : []; } } if (!function_exists('is_market_client')) { /** * 市场是否处于「客户机」模式(「谁是中心站」由 config/ywxapp.php 决定): * - market_mode=center → 强制中心站 * - market_mode=client → 强制客户机 * - market_mode=auto(默认): * · api_url 为空 → 本机即中心站(直接读写本地市场 wxapp_appmarket_addon_list) * · api_url 指向本机(同主机)→ 仍视为中心站(配置纠偏) * · api_url 指向其他主机 → 本机作为客户机,经 RemoteService 连接该中心站 * * auto 模式下依赖「当前请求主机」判定自身:改用框架 Request 抽象(可测试、CLI 可控), * 不再直接读 $_SERVER['HTTP_HOST']。CLI(路由缓存/refresh-menu)无法取得主机时保守判为客户机—— * 因此中心站请保持 api_url 为空,或显式设置 market_mode=center 以彻底解除该约束。 * @return bool */ function is_market_client(): bool { $mode = \think\facade\Config::get('ywxapp.market_mode', 'auto'); if ($mode === 'center') { return false; } if ($mode === 'client') { return true; } // auto:基于 api_url + 自身主机推导 $apiUrl = \think\facade\Config::get('ywxapp.api_url', ''); if (empty($apiUrl)) { return false; } $host = parse_url($apiUrl, PHP_URL_HOST); if (empty($host)) { return false; } // 用框架 Request 抽象主机(可 mock / CLI 可控),替代直接读 $_SERVER['HTTP_HOST'] $req = function_exists('request') ? request() : null; $self = $req ? (string) $req->host() : ''; if ($self === '') { // CLI(如路由缓存/refresh-menu)无法判定主机:回退到 market_mode 显式配置。 // 只有显式声明 market_mode=client 才当作客户机;否则(auto/center)按中心站处理, // 避免中心站 CLI 刷新菜单时误删 centerOnly 项(应用市场审核/开发者/收益等运营菜单)。 return \think\facade\Config::get('ywxapp.market_mode', 'auto') === 'client'; } $selfHost = preg_replace('/:\d+$/', '', $self); $cmpHost = preg_replace('/:\d+$/', '', $host); if (strcasecmp($selfHost, $cmpHost) === 0) { return false; // api_url 指向自身 = 视为中心站(配置纠偏) } return true; } }