index.php 2.5 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970
  1. <?php
  2. declare(strict_types=1);
  3. /**
  4. * Glacier 单一入口(前端控制器)。
  5. * 所有动态请求都经此进入 —— URL 与物理路径完全解耦,见 docs/architecture.md §3.1。
  6. */
  7. define('APP_ROOT', dirname(__DIR__));
  8. require APP_ROOT . '/vendor/autoload.php';
  9. use Glacier\Core\Config;
  10. use Glacier\Core\Logger;
  11. use Glacier\Core\Response;
  12. use Glacier\Core\Router;
  13. date_default_timezone_set('Asia/Shanghai'); // 架构约定 UTC+8
  14. $config = require APP_ROOT . '/app/config/env.php';
  15. Config::load($config);
  16. Logger::init(Config::get('storage.logs', APP_ROOT . '/storage/logs'));
  17. try {
  18. // 解析请求路径(去 query,规范化尾部斜杠)
  19. $path = parse_url($_SERVER['REQUEST_URI'] ?? '/', PHP_URL_PATH) ?: '/';
  20. if (strlen($path) > 1) {
  21. $path = rtrim($path, '/');
  22. }
  23. $method = $_SERVER['REQUEST_METHOD'] ?? 'GET';
  24. Logger::info('request', ['method' => $method, 'path' => $path]);
  25. // 注册路由(声明式路由表)
  26. $router = new Router();
  27. foreach ((array) require APP_ROOT . '/app/config/routes.php' as $route) {
  28. $router->add($route['method'], $route['pattern'], $route['handler'], $route['middleware'] ?? []);
  29. }
  30. $match = $router->match($path, $method);
  31. if ($match === null) {
  32. Logger::warning('route not found', ['method' => $method, 'path' => $path]);
  33. Response::html(
  34. '<!doctype html><html lang="zh-CN"><head><meta charset="utf-8"><title>404</title>'
  35. . '<style>body{font-family:system-ui;text-align:center;padding-top:80px;color:#666}'
  36. . 'h1{font-size:48px;color:#c33;margin-bottom:8px}</style></head>'
  37. . '<body><h1>404</h1><p>页面不存在。</p></body></html>',
  38. 404
  39. );
  40. }
  41. call_user_func($match['handler'], $match['params']);
  42. } catch (\Throwable $e) {
  43. Logger::error('uncaught exception', [
  44. 'message' => $e->getMessage(),
  45. 'file' => $e->getFile(),
  46. 'line' => $e->getLine(),
  47. ]);
  48. $detail = Config::get('app.debug', false)
  49. ? '<pre>' . e($e->getMessage()) . PHP_EOL . e($e->getFile() . ':' . $e->getLine()) . '</pre>'
  50. : '<p>服务器开小差了,请稍后再试。</p>';
  51. Response::html(
  52. '<!doctype html><html lang="zh-CN"><head><meta charset="utf-8"><title>500</title>'
  53. . '<style>body{font-family:system-ui;text-align:center;padding-top:80px;color:#666}'
  54. . 'h1{font-size:48px;color:#c33}</style></head>'
  55. . '<body><h1>500</h1>' . $detail . '</body></html>',
  56. 500
  57. );
  58. }