Method parameters

← Method parameters

Ashterix

docs: rewrite JsonRpcBundle docs, add SDK docs, move them under docs/api

en/docs/api/json-rpc-bundle/add_rpc_service/params.md new file +152 āˆ’0

1 + # Method parameters
2 +
3 + The parameters of an RPC method are the parameters of the PHP method. The bundle takes their names, types and default values from the signature and PHPDoc, builds a JSON Schema from them for the [documentation](/docs/api/json-rpc-bundle/documentation), and converts incoming values to the required types before the call.
4 +
5 + ## Scalar types
6 +
7 + `string`, `int`, `float`, `bool`, `array`, `mixed` and their nullable/union variants are passed as is. A parameter with a default value (including `null`) is optional.
8 +
9 + ```php
10 + public function search(string $query, int $limit = 20, ?string $sort = null): array
11 + ```
12 +
13 + A wrong type or a missing required parameter returns error `-32602` with a list of problems for each parameter — see [Error handling](/docs/api/json-rpc-bundle/error_handling).
14 +
15 + ## Exact types from PHPDoc
16 +
17 + If the native type is not enough (`array`), the exact type is taken from `@param`. Class names are resolved through the `use` imports of the procedure class.
18 +
19 + ```php
20 + /**
21 + * @param OrderItemDto[] $items
22 + * @param array<string, int|string> $meta
23 + */
24 + public function save(array $items, array $meta = []): bool
25 + ```
26 +
27 + ## DTO
28 +
29 + A parameter whose type is a class is automatically created from a JSON object:
30 +
31 + ```php
32 + final class CreateOrderDto
33 + {
34 + public function __construct(
35 + public string $sku,
36 + public int $qty = 1,
37 + ) {}
38 + }
39 +
40 + public function create(CreateOrderDto $order): int
41 + ```
42 +
43 + ```json
44 + {"jsonrpc": "2.0", "id": 1, "method": "Order.create", "params": {"order": {"sku": "A-1", "qty": 2}}}
45 + ```
46 +
47 + * A DTO collection is described in PHPDoc (`@param CreateOrderDto[] $orders`) — each array element becomes an object.
48 + * For union types (`FooDto|BarDto`), the first DTO that could be created is used.
49 + * A value from which a DTO cannot be created returns a validation error, not a raw array.
50 + * In the DTO schema, properties with a default value get `default`, and only properties without one go into `required`.
51 +
52 + ## Automatic conversion
53 +
54 + For parameters of the following types, the value is converted without additional attributes:
55 +
56 + | Parameter type | What the client passes | Converter |
57 + | --- | --- | --- |
58 + | `BackedEnum` | case value (`"paid"`) | `BackedEnumConvertor` |
59 + | pure enum | case name | `EnumConvertor` |
60 + | `DateTime`, `DateTimeImmutable`, `DateTimeInterface` | date string | `DateTimeConverter` |
61 + | `Symfony\Component\Uid\*`, `Ramsey\Uuid\*` | UUID string | `UuidConverter` |
62 + | Doctrine entity | identifier | `DoctrineEntityConverter` |
63 +
64 + ```php
65 + enum OrderStatus: string
66 + {
67 + case NEW = 'new';
68 + case PAID = 'paid';
69 + }
70 +
71 + /**
72 + * @param OrderStatus[] $statuses
73 + */
74 + public function find(OrderStatus $status, array $statuses = []): array
75 +
76 + // {"method": "Order.status", "params": {"order": 42}} — Order is loaded by id
77 + public function status(Order $order): string
78 + ```
79 +
80 + `DoctrineEntityConverter` is registered only when DoctrineBundle is enabled.
81 +
82 + In the response, these types are converted back to scalars: enum → value, date → string (`Y-m-d H:i:s`), UUID → string, entity → identifier (or `__toString()` for `Stringable`).
83 +
84 + ## `#[RPC\Param]`
85 +
86 + The attribute explicitly sets which scalar types the parameter accepts and which converter transforms the value. It is needed when the type is not supported automatically or a different converter is required.
87 +
88 + ```php
89 + public function __construct(
90 + int $type, // bitmask Param::STRING | Param::INT | Param::FLOAT | Param::NULL
91 + bool $collection = false, // the value is an array, each element is converted
92 + array $context = [], // for example, [Param::C_CONVERTOR => MyConvertor::class]
93 + )
94 + ```
95 +
96 + ```php
97 + use Ufo\RpcObject\RPC;
98 +
99 + public function charge(
100 + #[RPC\Param(RPC\Param::STRING, context: [RPC\Param::C_CONVERTOR => MoneyConvertor::class])]
101 + Money $amount,
102 + ): bool
103 + ```
104 +
105 + Predefined masks: `Param::NUMBER`, `Param::NULLABLE_STRING`, `Param::NULLABLE_NUMBER`, `Param::MIXED`.
106 +
107 + ## Custom converter
108 +
109 + Implement `Ufo\JsonRpcBundle\ParamConvertors\IParamConvertor`. With autoconfigure, the class automatically gets the `rpc.param_convertor` tag, and parameters of the supported type are converted without an attribute.
110 +
111 + ```php
112 + use Ufo\JsonRpcBundle\ParamConvertors\IParamConvertor;
113 + use Ufo\RpcObject\RPC\Param;
114 +
115 + final class MoneyConvertor implements IParamConvertor
116 + {
117 + public function toScalar(object $object, array $context = [], ?callable $callback = null): array|string|int|float|null
118 + {
119 + return $object->amount;
120 + }
121 +
122 + public function toObject(int|string|float|null $value, array $context = [], ?callable $callback = null): ?object
123 + {
124 + return new Money((int) $value);
125 + }
126 +
127 + public function supported(string $classFQCN): bool
128 + {
129 + return $classFQCN === Money::class;
130 + }
131 +
132 + public function getParamAttr(string $classFQCN): Param
133 + {
134 + return new Param(Param::INT, context: [Param::C_CONVERTOR => self::class]);
135 + }
136 + }
137 + ```
138 +
139 + ## Special `$rpc` parameters
140 +
141 + The `$rpc` object in `params` is not passed to the method; it controls how the request is executed:
142 +
143 + | Key | Purpose |
144 + | --- | --- |
145 + | `callback` | URL to send the result to — see [Webhook](/docs/api/json-rpc-bundle/functionality/callback) |
146 + | `timeout` | Execution timeout, seconds (default 10) |
147 + | `rayId` | Identifier of the parent request for tracing |
148 + | `ignoreCache` | `true` — bypass the [response cache](/docs/api/json-rpc-bundle/add_rpc_service/cache) and write it again |
149 +
150 + ```json
151 + {"jsonrpc": "2.0", "id": 1, "method": "Orders.get", "params": {"id": 10, "$rpc": {"ignoreCache": true}}}
152 + ```