tochka-developers/jsonrpc
Laravel package for building JSON-RPC 2.0 APIs, with server and client support, route registration, middleware, validation, and structured error handling. Expose PHP classes as RPC methods and call remote JSON-RPC services.
v6.0.0-beta.2 is a major, breaking release line. Treat it as a migration, not an upgrade. The only change in beta.2 over beta.1 is the addition of PHP 8.5 support — the breaking surface described below is unchanged.
Minimum steps to get running:
composer require <vendor>/<package>:6.0.0-beta.2 --with-all-dependencies
summary, description, allowParentMethods, and customCasters are all gone. Do not carry an old config file forward; re-publish and diff it against your existing one so you can see exactly what disappeared.JsonRpcController trait was removed. Anything extending or using it must be migrated to the package's current controller/base class before routes will resolve.ApiMethod attribute:
#[ApiMethod]
public function ping(): string
{
return 'pong';
}
Where to look first:
ApiMethod and ApiValidation attribute classes — these are now the primary extension points.summary and description moved out of config and into the spec itself.JsonRpcController removal doesn't break your bootstrap.First use case: expose a single read-only method (e.g. user.get) that takes one validated DTO parameter, then hit rpc.discover (or your schema endpoint) to confirm the method appears with the correct parameter schema. This exercises the three biggest v6 changes at once: attribute registration, reworked validation, and nested-object serialization.
Attribute-driven registration is now the only path. There is no implicit method discovery left. Every public method needs a #[ApiMethod] attribute. During migration, grep for public methods on your RPC classes and annotate them in bulk — anything unannotated is simply invisible to the dispatcher.
Validation with ApiValidation. The attribute still works on method parameters as before, but v6 also allows it on object fields. The practical pattern is to push validation down into your DTOs:
class CreateUserInput
{
#[ApiValidation(['required', 'email'])]
public string $email;
#[ApiValidation(['required', 'string', 'min:2'])]
public string $name;
public AddressInput $address; // nested object
}
Nested objects in parameters. v6 supports nested DTOs as API parameters, so model your request shapes as a small tree of value objects rather than flat scalar parameter lists. This is the cleanest way to take advantage of the new validation and schema generation. Keep DTOs free of framework dependencies where possible so they stay easy to unit test.
Replace customCasters with explicit construction. Since the caster hook is gone, do conversions in the DTO constructor, a static fromArray() factory, or directly in the method body. For enums, dates, and value objects, a dedicated factory method is usually cleaner than scattering casts across methods:
public static function fromArray(array $data): self
{
$input = new self();
$input->email = $data['email'];
$input->address = AddressInput::fromArray($data['address']);
return $input;
}
Documentation lives in the schema, not config. Because summary and description no longer come from config, keep method-level documentation in the OpenRPC spec source. If you have a CI step that generates or validates the schema, treat schema/code drift as a test failure rather than something you notice in production.
Testing pattern. Two layers pay off here: feature tests that dispatch real JSON-RPC requests through the HTTP endpoint (catching registration and dispatch problems), and unit tests directly against DTO validation (catching the reworked validation semantics quickly and cheaply). Add a smoke test that enumerates expected method names and asserts each one is discoverable. If you intend to run on PHP 8.5, run the matrix on both 8.3 and 8.5 so you don't trade compatibility for deprecation noise.
The silent-failure trap. A method missing #[ApiMethod] does not error at boot — it just isn't there. During migration this will look like "the method disappeared." Add a test that asserts the full expected method list against rpc.discover output.
Old config keys may be ignored or rejected. summary, description, allowParentMethods, and customCasters are removed from the config schema. If you keep an old config file around, expect either silent ignoring (making you think settings apply when they don't) or a validation error on boot. Re-publish and re-apply your customizations deliberately.
allowParentMethods removal changes inheritance behavior. If you relied on inherited parent methods being exposed automatically, they now need explicit #[ApiMethod] attributes — or explicit re-declaration on the child class. Audit base classes that previously provided shared RPC endpoints.
The validation rework is the highest-risk area. The release notes say validation was "reworked" without detail. Re-run your entire validation test suite and specifically re-test: optional vs. required fields, nullable values, nested object partial failure, and error message shapes (clients may assert on these). Do not assume pre-v6 behavior is preserved.
Nested-object errors need a client story. With nested DTOs, validation failures can now be deeply nested. Check how the error payload is structured and make sure your frontend/client can render field paths (address.city) rather than just top-level keys.
customCasters removal means boundary type mismatches. Anything that previously arrived as a string and got cast to a Carbon, enum, or UUID object now arrives raw unless you handle it. Grep for the caster registrations you had and map each one to an explicit DTO factory conversion.
JsonRpcController trait removal breaks bootstraps quietly. If a controller uses the removed trait, you get a fatal error — but if it merely extended something that provided the behavior, you may get method-not-found at request time. Check both use statements and inheritance chains.
PHP 8.5 support is new and only lightly exercised. Beta.2 adds 8.5 to the supported matrix, but it does not change the minimum (8.3). If your CI image or base Docker image pins 8.3/8.4, nothing forces you to move — upgrade the interpreter as a separate, isolated change so any deprecation or behaviour difference is attributable to the runtime and not to this package bump. Also verify your transitive RPC dependencies (serializers, schema generators) actually declare 8.5 support before adopting it in production.
Pin the beta exactly. This is 6.0.0-beta.2. Use an exact version constraint, not ^6.0, and don't roll it into production without a staging shakedown against your real method surface.
Debugging checklist when a method "vanishes": (1) is #[ApiMethod] present and imported from the correct namespace? (2) is the class in a path the package scans? (3) does the method pass the new validation on its own signature? (4) is the method listed in rpc.discover? Working through that order isolates registration from validation from serialization quickly.
How can I help you explore Laravel packages today?