Method parameters

Method parameters

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, and converts incoming values to the required types before the call.

Scalar types

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.

public function search(string $query, int $limit = 20, ?string $sort = null): array

A wrong type or a missing required parameter returns error -32602 with a list of problems for each parameter — see Error handling.

Exact types from PHPDoc

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.

/**
 * @param OrderItemDto[] $items
 * @param array<string, int|string> $meta
 */
public function save(array $items, array $meta = []): bool

DTO

A parameter whose type is a class is automatically created from a JSON object:

final class CreateOrderDto
{
    public function __construct(
        public string $sku,
        public int $qty = 1,
    ) {}
}

public function create(CreateOrderDto $order): int
{"jsonrpc": "2.0", "id": 1, "method": "Order.create", "params": {"order": {"sku": "A-1", "qty": 2}}}
  • A DTO collection is described in PHPDoc (@param CreateOrderDto[] $orders) — each array element becomes an object.
  • For union types (FooDto|BarDto), the first DTO that could be created is used.
  • A value from which a DTO cannot be created returns a validation error, not a raw array.
  • In the DTO schema, properties with a default value get default, and only properties without one go into required.

Automatic conversion

For parameters of the following types, the value is converted without additional attributes:

Parameter type What the client passes Converter
BackedEnum case value ("paid") BackedEnumConvertor
pure enum case name EnumConvertor
DateTime, DateTimeImmutable, DateTimeInterface date string DateTimeConverter
Symfony\Component\Uid\*, Ramsey\Uuid\* UUID string UuidConverter
Doctrine entity identifier DoctrineEntityConverter
enum OrderStatus: string
{
    case NEW = 'new';
    case PAID = 'paid';
}

/**
 * @param OrderStatus[] $statuses
 */
public function find(OrderStatus $status, array $statuses = []): array

// {"method": "Order.status", "params": {"order": 42}} — Order is loaded by id
public function status(Order $order): string

DoctrineEntityConverter is registered only when DoctrineBundle is enabled.

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).

#[RPC\Param]

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.

public function __construct(
    int $type,                 // bitmask Param::STRING | Param::INT | Param::FLOAT | Param::NULL
    bool $collection = false,  // the value is an array, each element is converted
    array $context = [],       // for example, [Param::C_CONVERTOR => MyConvertor::class]
)
use Ufo\RpcObject\RPC;

public function charge(
    #[RPC\Param(RPC\Param::STRING, context: [RPC\Param::C_CONVERTOR => MoneyConvertor::class])]
    Money $amount,
): bool

Predefined masks: Param::NUMBER, Param::NULLABLE_STRING, Param::NULLABLE_NUMBER, Param::MIXED.

Custom converter

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.

use Ufo\JsonRpcBundle\ParamConvertors\IParamConvertor;
use Ufo\RpcObject\RPC\Param;

final class MoneyConvertor implements IParamConvertor
{
    public function toScalar(object $object, array $context = [], ?callable $callback = null): array|string|int|float|null
    {
        return $object->amount;
    }

    public function toObject(int|string|float|null $value, array $context = [], ?callable $callback = null): ?object
    {
        return new Money((int) $value);
    }

    public function supported(string $classFQCN): bool
    {
        return $classFQCN === Money::class;
    }

    public function getParamAttr(string $classFQCN): Param
    {
        return new Param(Param::INT, context: [Param::C_CONVERTOR => self::class]);
    }
}

Special $rpc parameters

The $rpc object in params is not passed to the method; it controls how the request is executed:

Key Purpose
callback URL to send the result to — see Webhook
timeout Execution timeout, seconds (default 10)
rayId Identifier of the parent request for tracing
ignoreCache true — bypass the response cache and write it again
{"jsonrpc": "2.0", "id": 1, "method": "Orders.get", "params": {"id": 10, "$rpc": {"ignoreCache": true}}}