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);
// 从 manifest 获取 Master 扫描过的类
$manifestEntries = $scanner->getManifestClasses();
if (empty($manifestEntries)) {
\Kiri::getLogger()->warning('Annotation route rebuild: manifest is empty, annotation routes will NOT be registered');
$manifestClasses = [];
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;
}
@@ -323,84 +342,93 @@ class Router
$errorCount = 0;
$dispatchCount = 0;
foreach ($manifestEntries as $path => $entry) {
$classes = is_array($entry) && isset($entry['classes']) ? $entry['classes'] : [];
foreach ($classes as $class) {
if (!class_exists($class)) {
// 只处理用户命名空间下的类,排除框架和 PHP 内置类
$userNamespaces = $scanConfig['user_namespaces'] ?? ['App\\'];
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;
}
$classCount++;
try {
$reflect = $container->getReflectionClass($class);
if (!$reflect->isInstantiable() || $reflect->isTrait() || $reflect->isEnum() || $reflect->isInterface()) {
foreach ($reflect->getMethods() as $method) {
if ($method->isStatic() || $method->getDeclaringClass()->getName() !== $class) {
continue;
}
foreach ($reflect->getMethods() as $method) {
if ($method->isStatic() || $method->getDeclaringClass()->getName() !== $class) {
foreach ($method->getAttributes() as $attribute) {
$attrName = $attribute->getName();
if (!class_exists($attrName)) {
continue;
}
foreach ($method->getAttributes() as $attribute) {
$attrName = $attribute->getName();
if (!class_exists($attrName)) {
continue;
}
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()}");
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 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);
$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'];
foreach ($searchPaths as $searchPath) {
$found = [];
foreach ($manifestEntries as $path => $entry) {
$classes = is_array($entry) && isset($entry['classes']) ? $entry['classes'] : [];
foreach ($classes as $class) {
try {
$reflect = $container->getReflectionClass($class);
foreach ($reflect->getMethods() as $method) {
foreach ($method->getAttributes() as $attr) {
if (in_array($attr->getName(), [
\Kiri\Router\Annotate\Get::class,
\Kiri\Router\Annotate\Post::class,
\Kiri\Router\Annotate\Put::class,
\Kiri\Router\Annotate\Delete::class,
\Kiri\Router\Annotate\Route::class,
])) {
$instance = $attr->newInstance();
$routePath = $instance->path ?? '';
if (str_contains($routePath, 'header')) {
$found[] = "{$class}::{$method->getName()} -> {$attr->getName()} path={$routePath} version={$instance->version}";
}
foreach (array_keys($manifestClasses) as $class) {
if (!class_exists($class)) continue;
try {
$reflect = $container->getReflectionClass($class);
foreach ($reflect->getMethods() as $method) {
foreach ($method->getAttributes() as $attr) {
if (in_array($attr->getName(), [
\Kiri\Router\Annotate\Get::class,
\Kiri\Router\Annotate\Post::class,
\Kiri\Router\Annotate\Put::class,
\Kiri\Router\Annotate\Delete::class,
\Kiri\Router\Annotate\Route::class,
])) {
$instance = $attr->newInstance();
$routePath = $instance->path ?? '';
if (str_contains($routePath, 'header')) {
$version = $instance->version ?? '';
$found[] = "{$class}::{$method->getName()} path={$routePath} version={$version}";
}
}
}
} catch (\Throwable) {}
}
}
} catch (\Throwable) {}
}
if (!empty($found)) {
\Kiri::getLogger()->info("Annotation route search '{$searchPath}': " . implode(' | ', $found));
} 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");
}
}
}