No puede seleccionar más de 25 temas Los temas deben comenzar con una letra o número, pueden incluir guiones ('-') y pueden tener hasta 35 caracteres de largo.

132 líneas
3.2KB

  1. <?php
  2. namespace Framework\Routing;
  3. use Framework\Routing\Exception;
  4. use Throwable;
  5. class Router
  6. {
  7. protected array $routes = [];
  8. protected array $errorHandlers = [];
  9. protected Route $current;
  10. public function add(string $method, string $path, $handler): Route
  11. {
  12. $route = $this->routes[] = new Route($method, $path, $handler);
  13. return $route;
  14. }
  15. public function errorHandler(int $code, callable $handler)
  16. {
  17. $this->errorHandlers[$code] = $handler;
  18. }
  19. public function dispatch()
  20. {
  21. $paths = $this->paths();
  22. $requestMethod = $_SERVER['REQUEST_METHOD'] ?? 'GET';
  23. $requestPath = $_SERVER['REQUEST_URI'] ?? '/';
  24. $matching = $this->match($requestMethod, $requestPath);
  25. if ($matching) {
  26. $this->current = $matching;
  27. try {
  28. return $matching->dispatch();
  29. }
  30. catch (Throwable $e) {
  31. $result = null;
  32. if ($handler = config('handlers.exceptions')) {
  33. $instance = new $handler();
  34. if ($result = $instance->showThrowable($e)) {
  35. return $result;
  36. }
  37. }
  38. return $this->dispatchError();
  39. }
  40. }
  41. if (in_array($requestPath, $paths)) {
  42. return $this->dispatchNotAllowed();
  43. }
  44. return $this->dispatchNotFound();
  45. }
  46. private function paths(): array
  47. {
  48. $paths = [];
  49. foreach ($this->routes as $route) {
  50. $paths[] = $route->path();
  51. }
  52. return $paths;
  53. }
  54. public function current(): ?Route
  55. {
  56. return $this->current;
  57. }
  58. private function match(string $method, string $path): ?Route
  59. {
  60. foreach ($this->routes as $route) {
  61. if ($route->matches($method, $path)) {
  62. return $route;
  63. }
  64. }
  65. return null;
  66. }
  67. public function dispatchNotAllowed()
  68. {
  69. $this->errorHandlers[400] ??= fn() => 'not allowed';
  70. return $this->errorHandlers[400]();
  71. }
  72. public function dispatchNotFound()
  73. {
  74. $this->errorHandlers[404] ??= fn() => 'not found';
  75. return $this->errorHandlers[404]();
  76. }
  77. public function dispatchError()
  78. {
  79. $this->errorHandlers[500] ??= fn() => 'server error';
  80. return $this->errorHandlers[500]();
  81. }
  82. public function route(string $name, array $parameters = []): string
  83. {
  84. foreach ($this->routes as $route) {
  85. if ($route->name() === $name) {
  86. $finds = [];
  87. $replaces = [];
  88. foreach ($parameters as $key => $value) {
  89. array_push($finds, "{{$key}}");
  90. array_push($replaces, $value);
  91. array_push($finds, "{{$key}?}");
  92. array_push($replaces, $value);
  93. }
  94. $path = $route->path();
  95. $path = str_replace($finds, $replaces, $path);
  96. $path = preg_replace('#{[^}]+}#', '', $path);
  97. return $path;
  98. }
  99. }
  100. throw new Exception('No route with that name');
  101. }
  102. }

Powered by TurnKey Linux.