Custom API methods

← Custom API methods

Ashterix

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

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

1 + # Custom API methods
2 +
3 + Any application class becomes an API service if it implements the `Ufo\JsonRpcBundle\ApiMethod\Interfaces\IRpcService` interface. The interface imposes no logic — it only tags the class with `ufo.rpc.service`, which the bundle uses to build the method map when the container is compiled.
4 +
5 + Every public non-static method of such a class (except the constructor) becomes a JSON-RPC method named `<class name>.<method>`.
6 +
7 + ```php
8 + <?php
9 +
10 + namespace App\Api;
11 +
12 + use Ufo\JsonRpcBundle\ApiMethod\Interfaces\IRpcService;
13 + use Ufo\RpcObject\RPC;
14 +
15 + #[RPC\Info('Messenger')]
16 + class MessengerApi implements IRpcService
17 + {
18 + public function __construct(private Mailer $mailer) {}
19 +
20 + /**
21 + * A method for sending an email message
22 + * @param string $email The email address
23 + * @param string $text Message body
24 + * @param string $subject Optional message subject parameter
25 + */
26 + public function sendEmail(string $email, string $text, string $subject = 'Message without subject'): bool
27 + {
28 + return $this->mailer->send($email, $subject, $text);
29 + }
30 + }
31 + ```
32 +
33 + This example exposes the method `Messenger.sendEmail`:
34 +
35 + ::::columns
36 + :::col
37 + **Request**
38 + ```json
39 + {
40 + "jsonrpc": "2.0",
41 + "id": 1,
42 + "method": "Messenger.sendEmail",
43 + "params": {
44 + "email": "user@example.com",
45 + "text": "Hello!"
46 + }
47 + }
48 + ```
49 + :::
50 + :::col
51 + **Response**
52 + ```json
53 + {
54 + "jsonrpc": "2.0",
55 + "id": 1,
56 + "result": true
57 + }
58 + ```
59 + :::
60 + ::::
61 +
62 + Parameters can also be passed positionally: `"params": ["user@example.com", "Hello!"]`.
63 +
64 + :::info
65 + The method map is built when the container is compiled. After adding or changing methods in `prod`, run `bin/console cache:clear`.
66 + :::
67 +
68 + ## Naming
69 +
70 + Without the attribute, the class name in the API is the short class name (`MessengerApi.sendEmail`). The [`#[RPC\Info]`](/docs/api/json-rpc-bundle/add_rpc_service/info) attribute sets an alias (`Messenger.sendEmail`), the separator character and the [API version](/docs/api/json-rpc-bundle/functionality/versions).
71 +
72 + :::success subtitle="Good practice"
73 + Treat the class name as a namespace and the method name as an action: `Cart.addProduct`, `Cart.getProducts`, `Messenger.sendEmail`, `Messenger.sendSms`. This way, methods with the same name in different classes do not conflict (`Product.create`, `User.create`), and the names make it clear what the server can do.
74 + :::
75 +
76 + ## Describing methods and parameters
77 +
78 + The documentation is built from everything known about the method: names, native types, default values and docblocks. The description of the method and its parameters is taken from PHPDoc, and the exact type comes from `@param` / `@return` when the native type is not enough:
79 +
80 + ```php
81 + /**
82 + * Creates an order
83 + * @param OrderItemDto[] $items
84 + * @return array<string, OrderItemDto>
85 + */
86 + public function create(array $items, ?string $comment = null): array
87 + ```
88 +
89 + A parameter with a `null` default or any other default value is optional. Types are covered in detail on the [Method parameters](/docs/api/json-rpc-bundle/add_rpc_service/params) page, the result in [Response format](/docs/api/json-rpc-bundle/add_rpc_service/response).
90 +
91 + The method's name (`summary`) and description in the documentation can be translated without changing the code — see [API documentation](/docs/api/json-rpc-bundle/documentation).
92 +
93 + ## Deprecated methods
94 +
95 + A method with `@deprecated` in its docblock or with the `#[\Deprecated]` attribute is marked in OpenRPC as `"deprecated": true`, but keeps working.
96 +
97 + ```php
98 + /**
99 + * @deprecated use Orders.create
100 + */
101 + public function createOrder(array $items): array
102 + ```
103 +
104 + ## Hiding a method from the API
105 +
106 + Mark a public method that must not be an API method with `#[RPC\IgnoreApi]`: it appears neither in the method map nor in the documentation.
107 +
108 + ```php
109 + #[RPC\IgnoreApi]
110 + public function rebuildIndex(): void
111 + ```
112 +
113 + ## Services in method arguments
114 +
115 + Besides constructor injection, a service can be received directly in a method argument via `#[Autowire]`. Such an argument is not an RPC parameter: it is not in the documentation, and the client does not pass it.
116 +
117 + ```php
118 + use Symfony\Component\DependencyInjection\Attribute\Autowire;
119 +
120 + public function report(int $id, #[Autowire(service: 'app.report_builder')] ReportBuilder $builder): array
121 + ```
122 +
123 + :::warning
124 + In versions 10.0.1–10.3.0, `#[Autowire]` in method arguments did not work (fixed in 10.3.1). On these versions, use the constructor.
125 + :::
126 +
127 + ## RPC attributes
128 +
129 + | Attribute | Where | Purpose |
130 + | --- | --- | --- |
131 + | [`#[RPC\Info]`](/docs/api/json-rpc-bundle/add_rpc_service/info) | class | Alias, separator, API version, removed methods |
132 + | [`#[RPC\APIGroups]`](/docs/api/json-rpc-bundle/functionality/groups) | class, method | Which API groups the method belongs to |
133 + | [`#[RPC\Assertions]`](/docs/api/json-rpc-bundle/add_rpc_service/assertions) | parameter | Validation with Symfony constraints |
134 + | [`#[RPC\Param]`](/docs/api/json-rpc-bundle/add_rpc_service/params) | parameter | Explicit conversion of a value into an object |
135 + | [`#[RPC\DTO]`](/docs/api/json-rpc-bundle/add_rpc_service/response) | method, property | DTO format for a result or parameter |
136 + | [`#[RPC\Cache]`](/docs/api/json-rpc-bundle/add_rpc_service/cache) | method | Response caching |
137 + | [`#[RPC\CacheRelation]`](/docs/api/json-rpc-bundle/add_rpc_service/cache) | method | Invalidation of related cache |
138 + | [`#[RPC\Lock]`](/docs/api/json-rpc-bundle/add_rpc_service/lock) | method | Preventing concurrent calls |
139 + | `#[RPC\IgnoreApi]` | method | Remove the method from the API |
140 +
141 + All attributes come from the `ufo-tech/rpc-objects` package (namespace `Ufo\RpcObject\RPC`).