Route.php 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108
  1. <?php
  2. namespace Src;
  3. use Error;
  4. use FastRoute\RouteCollector;
  5. use FastRoute\RouteParser\Std;
  6. use FastRoute\DataGenerator\MarkBased;
  7. use FastRoute\Dispatcher\MarkBased as Dispatcher;
  8. use Src\Traits\SingletonTrait;
  9. class Route
  10. {
  11. //Используем методы трейта
  12. use SingletonTrait;
  13. //Свойство для хранения текущего маршрута
  14. private string $currentRoute = '';
  15. private $currentHttpMethod;
  16. //Свойство для префикса для всех маршрутов
  17. private string $prefix = '';
  18. //Классы для использования внешнего маршрутизатора
  19. private RouteCollector $routeCollector;
  20. //Добавляет маршрут, устанавливает его текущим и возвращает объект
  21. public static function add($httpMethod, string $route, array $action): self
  22. {
  23. self::single()->routeCollector->addRoute($httpMethod, $route, $action);
  24. self::single()->currentHttpMethod = $httpMethod;
  25. self::single()->currentRoute = $route;
  26. return self::single();
  27. }
  28. //Добавляет префикс для обозначенных маршрутов
  29. public static function group(string $prefix, callable $callback): void
  30. {
  31. self::single()->routeCollector->addGroup($prefix, $callback);
  32. Middleware::single()->group($prefix, $callback);
  33. }
  34. //Конструктор скрыт. Вызывается только один раз
  35. private function __construct()
  36. {
  37. $this->routeCollector = new RouteCollector(new Std(), new MarkBased());
  38. }
  39. public function setPrefix(string $value = ''): self
  40. {
  41. $this->prefix = $value;
  42. return $this;
  43. }
  44. public function redirect(string $url): void
  45. {
  46. header('Location: ' . $this->getUrl($url));
  47. }
  48. public function getUrl(string $url): string
  49. {
  50. return $this->prefix . $url;
  51. }
  52. //Добавление middlewares для текущего маршрута
  53. public function middleware(...$middlewares): self
  54. {
  55. Middleware::single()->add($this->currentHttpMethod, $this->currentRoute, $middlewares);
  56. return $this;
  57. }
  58. public function save()
  59. {
  60. Settings::addUri($this->prefix . '.' . $this->currentRoute);
  61. }
  62. public function start(): void
  63. {
  64. // Fetch method and URI from somewhere
  65. $httpMethod = $_SERVER['REQUEST_METHOD'];
  66. $uri = $_SERVER['REQUEST_URI'];
  67. // Strip query string (?foo=bar) and decode URI
  68. if (false !== $pos = strpos($uri, '?')) {
  69. $uri = substr($uri, 0, $pos);
  70. }
  71. $uri = rawurldecode($uri);
  72. $uri = substr($uri, strlen($this->prefix));
  73. $dispatcher = new Dispatcher($this->routeCollector->getData());
  74. $routeInfo = $dispatcher->dispatch($httpMethod, $uri);
  75. switch ($routeInfo[0]) {
  76. case Dispatcher::NOT_FOUND:
  77. throw new Error('NOT_FOUND');
  78. case Dispatcher::METHOD_NOT_ALLOWED:
  79. throw new Error('METHOD_NOT_ALLOWED');
  80. case Dispatcher::FOUND:
  81. $handler = $routeInfo[1];
  82. $vars = array_values($routeInfo[2]);
  83. //Вызываем обработку всех Middleware
  84. $vars[] = Middleware::single()->go($httpMethod, $uri, new Request());
  85. $class = $handler[0];
  86. $action = $handler[1];
  87. call_user_func([new $class, $action], ...$vars);
  88. break;
  89. }
  90. }
  91. }