damienfern / grpc-symfony-bundle
Wire generated protobuf service interfaces to Symfony services and dispatch gRPC/HTTP RPCs to them, with zero manual service registration.
Package info
github.com/damienfern/grpc-symfony-bundle
Language:Go
Type:symfony-bundle
pkg:composer/damienfern/grpc-symfony-bundle
Requires
- php: >=8.2
- google/protobuf: ^5.36
- psr/container: ^2.0
- symfony/dependency-injection: ^7.0
- symfony/http-kernel: ^7.0
Requires (Dev)
None
Suggests
None
Provides
None
Conflicts
None
Replaces
None
This package is auto-updated.
Last update: 2026-09-18 11:39:18 UTC
README
Wires generated protobuf service interfaces to Symfony services, and dispatches gRPC/HTTP RPCs to them, with zero manual service registration. Extracted from a proof-of-concept (grpc-symfony) so any Symfony app exposing gRPC can reuse the same pattern.
What's in here
src/GrpcServiceInterface.php— marker interface. Every proto service interface generated bytools/protoc-gen-php-grpc-serviceextends it.src/GrpcRouter.php— dispatches an RPC (by method name) to the Symfony service implementing it, reading the request's PHP class straight off the handler method's parameter type via reflection.src/GrpcSymfonyBundle.php+src/DependencyInjection/— registering the bundle auto-tags any class implementingGrpcServiceInterfaceand buildsGrpcRouter's whole RPC-method -> handler dispatch table at container-compile time. Nothing to add to yourservices.yaml, ever, not even for a new RPC on an existing service.tools/protoc-gen-php-grpc-service/— a protoc plugin generating one PHP interface per proto service (the official PHP protoc output only emits message classes, never server-side interfaces). Ships prebuilt for linux-amd64 and darwin-arm64 asvendor/bin/protoc-gen-php-grpc-service(see "Usage" below) — no Go toolchain needed on those platforms. Other platforms: build it yourself from this directory (see itsMakefile).tools/protoc-gen-go-grpc-bridge/— a protoc plugin generating, for a Go gRPC server, one struct per proto service that forwards every RPC to acallPHP(ctx, method, req, resp)function you provide (see step 2 in "Usage" below). Ships prebuilt for linux-amd64 and darwin-arm64 asvendor/bin/protoc-gen-go-grpc-bridge, same as the PHP plugin. Only needed if your Go gRPC server calls out to PHP the same way the original POC does (e.g. viafrankenphp-grpc); skip it if your Go server is wired some other way.
Usage
-
Require the bundle and enable it:
composer require dfernandes/grpc-symfony-bundle// config/bundles.php return [ // ... GrpcSymfony\GrpcSymfonyBundle::class => ['all' => true], ];
-
Generate a service interface per proto service, pointing protoc at the plugin the bundle already ships in
vendor/bin/:protoc \ --plugin=protoc-gen-php-grpc-service=vendor/bin/protoc-gen-php-grpc-service \ --php_out=proto/php \ --php-grpc-service_out=proto/php \ your.proto
This generates e.g.
Helloworld\GreeterServiceInterface, extending\GrpcSymfony\GrpcServiceInterfaceby default. Pass--php-grpc-service_opt=marker=\Some\Other\Interfaceif you don't want the bundle's own dispatch table.If your Go gRPC server needs a per-service bridge struct forwarding every RPC to PHP, add
protoc-gen-go-grpc-bridgeto the same invocation — it's prebuilt invendor/bin/too:protoc \ --plugin=protoc-gen-php-grpc-service=vendor/bin/protoc-gen-php-grpc-service \ --plugin=protoc-gen-go-grpc-bridge=vendor/bin/protoc-gen-go-grpc-bridge \ --php_out=proto/php \ --php-grpc-service_out=proto/php \ --go-grpc-bridge_out=<dir> --go-grpc-bridge_opt=package=<pkg> \ your.proto
This is only needed if your Go gRPC server calls out to PHP the same way the original POC does (e.g. via
frankenphp-grpc); skip it if your Go server is wired some other way. It assumes acallPHP(ctx, method string, req, resp proto.Message) errorfunction exists in the target package — see the original POC'sgrpc/server.gofor a worked example. -
Implement the generated interface with an ordinary Symfony service — no tagging, no
services.yamlentry:final class GreeterHandler implements \Helloworld\GreeterServiceInterface { public function sayHello(\Helloworld\HelloRequest $request): \Helloworld\HelloReply { return (new \Helloworld\HelloReply())->setMessage("Hello, {$request->getName()}"); } }
-
Dispatch a request through
GrpcSymfony\GrpcRouter(fetched from the container, e.g. from a gRPC worker entry point, or injected into another service like an HTTP controller):$router->route('SayHello', $binaryProtobufPayload); // raw protobuf wire format $router->routeJson('SayHello', $jsonPayload); // protobuf JSON