This commit is contained in:
2026-06-24 21:02:16 +08:00
parent 5a1aa2d60f
commit 7455dc8d58
+81 -53
View File
@@ -312,9 +312,28 @@ class Router
); );
$scanner->setConfig($scanConfig); $scanner->setConfig($scanConfig);
// 从 manifest 获取 Master 扫描过的类
$manifestEntries = $scanner->getManifestClasses(); $manifestEntries = $scanner->getManifestClasses();
if (empty($manifestEntries)) { $manifestClasses = [];
\Kiri::getLogger()->warning('Annotation route rebuild: manifest is empty, annotation routes will NOT be registered'); foreach ($manifestEntries as $entry) {
if (is_array($entry) && isset($entry['classes'])) {
foreach ($entry['classes'] as $c) {
$manifestClasses[$c] = true;
}
}
}
// 关键:manifest 只包含 Scanner 通过 require_once 新发现的类
// 但路由文件加载时 $container->get(Controller) 会触发 autoload 提前加载类
// 导致 Scanner 的 require_once 变成 no-op,该类及其注解永久丢失
// 因此必须合并 get_declared_classes() 补扫所有已声明的用户空间类
$allDeclared = get_declared_classes();
foreach ($allDeclared as $class) {
$manifestClasses[$class] = true;
}
if (empty($manifestClasses)) {
\Kiri::getLogger()->warning('Annotation route rebuild: no classes to process');
return; return;
} }
@@ -323,84 +342,93 @@ class Router
$errorCount = 0; $errorCount = 0;
$dispatchCount = 0; $dispatchCount = 0;
foreach ($manifestEntries as $path => $entry) { // 只处理用户命名空间下的类,排除框架和 PHP 内置类
$classes = is_array($entry) && isset($entry['classes']) ? $entry['classes'] : []; $userNamespaces = $scanConfig['user_namespaces'] ?? ['App\\'];
foreach ($classes as $class) {
if (!class_exists($class)) { foreach (array_keys($manifestClasses) as $class) {
$isUserClass = false;
foreach ($userNamespaces as $ns) {
if (str_starts_with($class, $ns)) {
$isUserClass = true;
break;
}
}
if (!$isUserClass) {
continue;
}
if (!class_exists($class)) {
continue;
}
$classCount++;
try {
$reflect = $container->getReflectionClass($class);
if (!$reflect->isInstantiable() || $reflect->isTrait() || $reflect->isEnum() || $reflect->isInterface() || $reflect->isAbstract()) {
continue; continue;
} }
$classCount++; foreach ($reflect->getMethods() as $method) {
try { if ($method->isStatic() || $method->getDeclaringClass()->getName() !== $class) {
$reflect = $container->getReflectionClass($class);
if (!$reflect->isInstantiable() || $reflect->isTrait() || $reflect->isEnum() || $reflect->isInterface()) {
continue; continue;
} }
foreach ($reflect->getMethods() as $method) { foreach ($method->getAttributes() as $attribute) {
if ($method->isStatic() || $method->getDeclaringClass()->getName() !== $class) { $attrName = $attribute->getName();
if (!class_exists($attrName)) {
continue; continue;
} }
foreach ($method->getAttributes() as $attribute) { try {
$attrName = $attribute->getName(); $instance = $attribute->newInstance();
if (!class_exists($attrName)) { if ($instance instanceof Kiri\Di\Interface\InjectMethodInterface) {
continue; $instance->dispatch($class, $method->getName());
} $dispatchCount++;
try {
$instance = $attribute->newInstance();
if ($instance instanceof Kiri\Di\Interface\InjectMethodInterface) {
$instance->dispatch($class, $method->getName());
$dispatchCount++;
}
} catch (\Throwable $e) {
$errorCount++;
\Kiri::getLogger()->error("Annotation rebuild error [{$class}::{$method->getName()} @ {$attrName}]: {$e->getMessage()}");
} }
} catch (\Throwable $e) {
$errorCount++;
\Kiri::getLogger()->error("Annotation rebuild error [{$class}::{$method->getName()} @ {$attrName}]: {$e->getMessage()}");
} }
} }
} catch (\Throwable $e) {
$errorCount++;
\Kiri::getLogger()->error("Annotation rebuild class [{$class}]: {$e->getMessage()}");
} }
} catch (\Throwable $e) {
$errorCount++;
\Kiri::getLogger()->error("Annotation rebuild class [{$class}]: {$e->getMessage()}");
} }
} }
$router = $container->get(DataGrip::class)->get(static::$type); $router = $container->get(DataGrip::class)->get(static::$type);
$routeCount = count($router->dump()); $routeCount = count($router->dump());
\Kiri::getLogger()->info("Annotation route rebuild: {$classCount} classes processed, {$dispatchCount} annotation routes dispatched, {$routeCount} total routes, {$errorCount} errors"); \Kiri::getLogger()->info("Annotation route rebuild: {$classCount} user classes processed, {$dispatchCount} annotation routes dispatched, {$routeCount} total routes, {$errorCount} errors");
// 搜索特定路径的诊断日志,方便排查 404 问题 // 搜索特定路径的诊断日志
$searchPaths = ['/headers']; $searchPaths = ['/headers'];
foreach ($searchPaths as $searchPath) { foreach ($searchPaths as $searchPath) {
$found = []; $found = [];
foreach ($manifestEntries as $path => $entry) { foreach (array_keys($manifestClasses) as $class) {
$classes = is_array($entry) && isset($entry['classes']) ? $entry['classes'] : []; if (!class_exists($class)) continue;
foreach ($classes as $class) { try {
try { $reflect = $container->getReflectionClass($class);
$reflect = $container->getReflectionClass($class); foreach ($reflect->getMethods() as $method) {
foreach ($reflect->getMethods() as $method) { foreach ($method->getAttributes() as $attr) {
foreach ($method->getAttributes() as $attr) { if (in_array($attr->getName(), [
if (in_array($attr->getName(), [ \Kiri\Router\Annotate\Get::class,
\Kiri\Router\Annotate\Get::class, \Kiri\Router\Annotate\Post::class,
\Kiri\Router\Annotate\Post::class, \Kiri\Router\Annotate\Put::class,
\Kiri\Router\Annotate\Put::class, \Kiri\Router\Annotate\Delete::class,
\Kiri\Router\Annotate\Delete::class, \Kiri\Router\Annotate\Route::class,
\Kiri\Router\Annotate\Route::class, ])) {
])) { $instance = $attr->newInstance();
$instance = $attr->newInstance(); $routePath = $instance->path ?? '';
$routePath = $instance->path ?? ''; if (str_contains($routePath, 'header')) {
if (str_contains($routePath, 'header')) { $version = $instance->version ?? '';
$found[] = "{$class}::{$method->getName()} -> {$attr->getName()} path={$routePath} version={$instance->version}"; $found[] = "{$class}::{$method->getName()} path={$routePath} version={$version}";
}
} }
} }
} }
} catch (\Throwable) {} }
} } catch (\Throwable) {}
} }
if (!empty($found)) { if (!empty($found)) {
\Kiri::getLogger()->info("Annotation route search '{$searchPath}': " . implode(' | ', $found)); \Kiri::getLogger()->info("Annotation route search '{$searchPath}': " . implode(' | ', $found));
} else { } else {
\Kiri::getLogger()->warning("Annotation route search '{$searchPath}': NO annotation found in any of {$classCount} classes"); \Kiri::getLogger()->warning("Annotation route search '{$searchPath}': NO annotation found in any class");
} }
} }
} }