fork download
  1. <?php
  2.  
  3.  
  4. bootstrap();
  5. function bootstrap()
  6. {
  7. // Инициализируем всё.
  8. $users = new UserStore();
  9. $userCarts = new UserCartStore();
  10. $products = new ProductStore();
  11. $controller = new CartController(
  12. $users,
  13. $userCarts,
  14. $products
  15. );
  16. $httpHandler = new HttpCartHandler(
  17. $controller
  18. );
  19. $router = new Router();
  20.  
  21. // Настраиваем роутер.
  22. $router->onNothing(static function () {
  23. print 'Unexpected route';
  24. });
  25. $router->addRoute('/cart/add', static function () use ($httpHandler) {
  26. $httpHandler->addProductToCart();
  27. });
  28.  
  29. // Запускаем роутер, он вызовет хендлер, тот контроллер, а тот базы данных.
  30. $router->route($_SERVER['REQUEST_URI']); // REQUEST_URI - это не совсем то, я для примера написал.
  31. }
  32.  
  33. class Router
  34. {
  35. protected $routes = [];
  36. protected $onNothing;
  37.  
  38. public function addRoute($path, callable $callback)
  39. {
  40. $this->routes[$path] = $callback;
  41. }
  42.  
  43. public function onNothing(callable $callback)
  44. {
  45. $this->onNothing = $callback;
  46. }
  47.  
  48. public function route($path)
  49. {
  50. if (!empty($this->routes[$path])) {
  51. $this->routes[$path]();
  52. } elseif (!empty($this->onNothing)) {
  53. ($this->onNothing)();
  54. } else {
  55. throw new Exception('No "nothing" callback was configured');
  56. }
  57. }
  58.  
  59. }
  60.  
  61.  
  62. class HttpCartHandler
  63. {
  64.  
  65. /** @var CartController */
  66. protected $cartController;
  67.  
  68. public function __construct(CartController $cartController)
  69. {
  70. $this->cartController = $cartController;
  71. }
  72.  
  73. public function addProductToCart()
  74. {
  75. $userId = $_POST['user_id'] ?? null;
  76. $productId = $_POST['product_id'] ?? null;
  77.  
  78. try {
  79. $this->cartController->addProductToCart(
  80. $userId,
  81. $productId
  82. );
  83. print 'Successfully added'; // Для принтов по идее нужен отдельный класс-Renderer;
  84. } catch (InvalidArgumentException $e) {
  85. print 'Invalid argument: ' . $e->getMessage();
  86. } catch (\Throwable $e) {
  87. error_log((string) $e);
  88. print 'Internal error';
  89. }
  90. }
  91. }
  92.  
  93. class CartController
  94. {
  95. // В реальном коде тут были бы интерфейсы, я же пока захардкодил сразу классы.
  96. /** @var UserStore */
  97. protected $users;
  98. /** @var UserCartStore */
  99. protected $userCarts;
  100. /** @var ProductStore */
  101. protected $products;
  102.  
  103. /**
  104.   * @param UserStore $users
  105.   * @param UserCartStore $userCarts
  106.   * @param ProductStore $products
  107.   */
  108. public function __construct($users, $userCarts, $products)
  109. {
  110. $this->users = $users;
  111. $this->userCarts = $userCarts;
  112. $this->products = $products;
  113. }
  114.  
  115. public function addProductToCart($userId, $productId)
  116. {
  117. $user = $this->users->load($userId);
  118. if ($user === null) {
  119. throw new InvalidArgumentException('invalid user id');
  120. }
  121. $product = $this->products->load($productId);
  122. if ($product === null) {
  123. throw new InvalidArgumentException('invalid product id');
  124. }
  125.  
  126. $this->userCarts->addProduct($userId, $productId);
  127. }
  128. }
  129.  
  130. class UserCartStore
  131. {
  132. public function addProduct($userId, $productId)
  133. {
  134.  
  135. }
  136. }
  137.  
  138. class UserStore
  139. {
  140. public function load($userId)
  141. {
  142.  
  143. }
  144. }
  145.  
  146. class ProductStore
  147. {
  148. public function load($productId)
  149. {
  150.  
  151. }
  152. }
  153.  
Success #stdin #stdout #stderr 0.02s 24444KB
stdin
1
2
10
42
11
stdout
Unexpected route
stderr
PHP Notice:  Undefined index: REQUEST_URI in /home/ejpRTD/prog.php on line 30