getProperty('rules'); $prop->setAccessible(true); $rules = $prop->getValue(); $getBucket = isset($rules['get']) ? $rules['get'] : []; $starBucket = isset($rules['*']) ? $rules['*'] : []; $out = [ 'request_path' => $this->request->path(), 'request_pathinfo' => $this->request->pathinfo(), 'request_module' => $this->request->module(), 'request_controller' => $this->request->controller(), 'request_action' => $this->request->action(), 'server_PATH_INFO' => isset($_SERVER['PATH_INFO']) ? $_SERVER['PATH_INFO'] : null, 'get_s' => isset($_GET['s']) ? $_GET['s'] : null, 'url_route_on' => Config::get('url_route_on'), 'route_config_file' => Config::get('route_config_file'), 'pathinfo_depr' => Config::get('pathinfo_depr'), 'CONF_PATH' => CONF_PATH, 'route_file_exists' => is_file(CONF_PATH . 'route.php'), 'runtime_route_file' => is_file(RUNTIME_PATH . 'route.php'), 'rule_buckets' => array_keys($rules), 'get_bucket_count' => count($getBucket), 'star_bucket_count' => count($starBucket), 'get_sample' => array_slice(array_keys($getBucket), 0, 8), 'has_static_rule' => isset($getBucket['api/v1/home/banners']), 'star_has_static' => isset($starBucket['api/v1/home/banners']), ]; // —— 追加:文件真实内容 & OPcache 取证 —— $rf = CONF_PATH . 'route.php'; $out['route_file_realpath'] = is_file($rf) ? realpath($rf) : null; $out['route_file_size'] = is_file($rf) ? filesize($rf) : -1; $out['route_file_mtime'] = is_file($rf) ? date('c', filemtime($rf)) : null; $loaded = is_file($rf) ? include $rf : null; $out['included_is_array'] = is_array($loaded); $out['included_rule_count'] = is_array($loaded) ? count($loaded) : -1; $out['included_keys'] = is_array($loaded) ? array_slice(array_keys($loaded), 0, 4) : null; $out['opcache_enabled'] = function_exists('opcache_get_status') ? (bool)@opcache_get_status(false)['opcache_enabled'] : null; $out['ini_validate_ts'] = ini_get('opcache.validate_timestamps'); $out['ini_revalidate'] = ini_get('opcache.revalidate_freq'); $out['ini_opcache_on'] = ini_get('opcache.enable'); if (function_exists('opcache_get_status')) { $st = @opcache_get_status(true); if (!empty($st['scripts'])) { foreach ($st['scripts'] as $path => $info) { if (strpos($path, '/application/route.php') !== false) { $out['opcache_cached_route'] = [ 'path' => $path, 'timestamp' => date('c', $info['timestamp']), 'hits' => $info['hits'], ]; } } } } // —— 决定性测试:手动 import 后,规则是否进入 Route::$rules —— $out['star_keys_before'] = array_slice(array_keys($starBucket), 0, 5); $apiKeysBefore = []; foreach ($rules as $bucket => $items) { foreach (array_keys((array)$items) as $k) { if (strpos($k, 'api/v1') === 0) { $apiKeysBefore[] = $bucket . ' :: ' . $k; } } } $out['api_v1_rules_before'] = array_slice($apiKeysBefore, 0, 5); $out['api_v1_count_before'] = count($apiKeysBefore); if (is_array($loaded)) { Route::import($loaded); $prop2 = $ref->getProperty('rules'); $prop2->setAccessible(true); $rules2 = $prop2->getValue(); $apiKeysAfter = []; foreach ($rules2 as $bucket => $items) { foreach (array_keys((array)$items) as $k) { if (strpos($k, 'api/v1') === 0) { $apiKeysAfter[] = $bucket . ' :: ' . $k; } } } $out['api_v1_count_after_manual_import'] = count($apiKeysAfter); $out['star_count_after'] = isset($rules2['*']) ? count($rules2['*']) : 0; $out['get_count_after'] = isset($rules2['get']) ? count($rules2['get']) : 0; } $out['app_debug'] = \think\Config::get('app_debug'); echo json_encode($out, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT); exit; } }