docs: rewrite JsonRpcBundle docs, add SDK docs, move them under docs/api
uk/docs/api/json-rpc-bundle/functionality/events/pre_execute.md
новий файл +127
−0
rpc.pre_execute
Назва події
rpc.pre_execute
Константа
RpcEvent::PRE_EXECUTE
Клас
RpcPreExecuteEvent
Властивості
RpcRequest $rpcRequest, Service $service, array $params
Найважливіша подія: на ній бандл валідує й конвертує параметри, захоплює блокування і виконує сам метод. Ваш лістенер стає частиною цього конвеєра — де саме, визначає пріоритет.
Коли генерується
Один раз на кожне виконання методу: після промаху кешу й після того, як метод знайдено. Для будь-якого джерела запиту — HTTP, консоль, batch, Messenger, відкладене виконання notifications/callback, прогрів кешу.
Не генерується для кешованої відповіді, невідомого методу і прийому notifications/callback (метод виконується пізніше, і тоді подія буде).
Вбудовані лістенери
| Пріоритет | Лістенер | Що робить |
|---|---|---|
| 1002 | ValidateParamsListener |
Перетворює параметри на список аргументів методу (іменовані й позиційні), підставляє значення за замовчуванням і сервіси з #[Autowire]. Перезаписує $event->params. Відсутні обов'язкові параметри — rpc.error |
| 1001 | ValidateParamsListener::constraintValidation |
Перевіряє #[RPC\Assertions]; порушення — rpc.error |
| 1000 | ParamsConverterEventListener |
Конвертує скаляри в об'єкти й масиви в DTO |
| -100 | LockEventListener |
Якщо запит уже має помилку — rpc.error; інакше захоплює #[RPC\Lock] |
| -1000 | RpcServerListener |
Викликає метод з $event->params, формує відповідь (rpc.pre_response), генерує rpc.post_execute і зупиняє поширення |
Що можна змінити
$event->params — це саме ті аргументи, з якими буде викликано метод. Ефект залежить від пріоритету:
| Пріоритет лістенера | Що ви бачите і що змінюєте |
|---|---|
| понад 1002 | Сирі параметри запиту; ваші зміни буде перезаписано на 1002 |
| між 1002 і 1000 | Список аргументів зі скалярами; зміни пройдуть валідацію і конвертацію |
| між 1000 і -1000 | Готові аргументи (об'єкти, DTO); зміни передаються в метод як є |
| нижче -1000 | Викликається лише на шляху помилки виконання |
- Ключ кешу рахується з сирих параметрів запиту, тож зміни
$paramsна нього не впливають. - Замінювати
$event->rpcRequestне варто — це розсинхронізує сервер.
Зупинка поширення пропускає виклик методу. Підтримується лише сценарій помилки: згенеруйте rpc.error і зупиніть подію — так роблять вбудовані лістенери. Повернути успішний результат без виклику методу штатного способу немає.
public function __construct(private RpcEventFactory $events) {}
// ...
$this->events->fireError($event->rpcRequest, new RpcLogicException('Not allowed'));
$event->stopPropagation();
Приклади використання
Значення параметра з контексту
Підставити ідентифікатор поточного клієнта замість того, що передав клієнт (захист від підміни):
#[AsEventListener(RpcEvent::PRE_EXECUTE, priority: 1001)]
final class TenantParamListener
{
public function __construct(private TenantResolver $tenants) {}
public function __invoke(RpcPreExecuteEvent $event): void
{
if (array_key_exists('tenantId', $event->params)) {
$event->params['tenantId'] = $this->tenants->current();
}
}
}
Пріоритет 1001: після формування списку аргументів (1002), але до конвертації (1000).
Перевірка доступу до методу
#[AsEventListener(RpcEvent::PRE_EXECUTE, priority: 999)]
final class AccessListener
{
public function __construct(private RpcEventFactory $events, private Acl $acl) {}
public function __invoke(RpcPreExecuteEvent $event): void
{
if (!$this->acl->canCall($event->service->name)) {
$this->events->fireError($event->rpcRequest, new RpcLogicException('Access denied'));
$event->stopPropagation();
}
}
}
Інші ідеї
- вимірювання часу виконання (старт тут, фініш на
rpc.post_execute/rpc.error); - відкриття транзакції Doctrine перед виконанням методу;
- аудит змін: збереження параметрів методів, що змінюють дані.