1final class OrderService
2{
3 public function place(Cart $cart, Customer $customer): Order
4 {
5 $order = Order::fromCart($cart, $customer);
6 $this->orders->save($order);
7
8 $this->mailer->send(new ReceiptMail($order));
9 $this->warehouse->reserve($order->items());
10 $this->telegram->notifyManagers("Нове замовлення {$order->number}");
11 $this->checkbox->fiscalize($order);
12 // $this->novaPoshta->createWaybill($order);
13
14 return $order;
15 }
16}
1<?php
2
31final readonly class OrderPlaced
4{
5 public function __construct(public string $number, public string $email, public int $total) {}
6}
7
8final class EventDispatcher
9{
10 /** @var array<string, list<callable>> */
11 private array $listeners = [];
12
13 public function listen(string $event, callable $listener): void
14 {
15 $this->listeners[$event][] = $listener;
16 }
17
182 public function dispatch(object $event): void
19 {
20 foreach ($this->listeners[$event::class] ?? [] as $listener) {
21 $listener($event);
22 }
23 }
24}
25
26final class SendReceipt
27{
28 public function __invoke(OrderPlaced $event): void
29 {
30 echo "Лист на {$event->email}: замовлення {$event->number}, {$event->total} грн\n";
31 }
32}
33
34final class ReserveStock
35{
36 public function __invoke(OrderPlaced $event): void
37 {
38 echo "Склад: товар для {$event->number} зарезервовано\n";
39 }
40}
41
42final class NotifyTelegram
43{
44 public function __invoke(OrderPlaced $event): void
45 {
46 echo "Telegram менеджерам: нове замовлення {$event->number}\n";
47 }
48}
49
503final class Checkout
51{
52 public function __construct(private EventDispatcher $events) {}
53
54 public function place(string $number, string $email, int $total): void
55 {
56 echo "Замовлення {$number} збережено\n";
57 $this->events->dispatch(new OrderPlaced($number, $email, $total));
58 }
59}
60
614$events = new EventDispatcher();
62$events->listen(OrderPlaced::class, new SendReceipt());
63$events->listen(OrderPlaced::class, new ReserveStock());
64$events->listen(OrderPlaced::class, new NotifyTelegram());
65
66(new Checkout($events))->place('UA-1042', 'olena@example.com', 1850);