gRPC Support
The Beauty Framework provides optional support for gRPC services via the beauty-framework/grpc
package, built on top of the official RoadRunner gRPC plugin.
⚠️ This is an optional module. You need to install and configure it manually.
📦 Installation
Install the package:
make composer require beauty-framework/grpc
# or without Docker
composer require beauty-framework/grpc
Run the setup command:
make beauty grpc:install
# or without Docker
./beauty grpc:install
This will:
- Create the
generated/
directory for compiled classes - Add
"GRPC\\": "generated/"
namespace to yourcomposer.json
- Copy
grpc-worker.php
into theworkers/
directory - Download the
protoc-gen-php-grpc
binary if needed
You should also update your Makefile
with the grpcgen
command:
grpcgen:
docker-compose exec $(APP_CONTAINER) chmod +x /usr/local/bin/protoc-gen-php-grpc
docker-compose exec -it $(APP_CONTAINER) protoc --plugin=protoc-gen-php-grpc \
--php_out=./generated \
--php-grpc_out=./generated \
$(filter-out $@,$(MAKECMDGOALS))
And add grpcgen
to the .PHONY
section.
🔧 Configuration
Update .rr.yaml
:
.rr.yaml
grpc:
listen: tcp://0.0.0.0:51015
pool:
command: "php workers/grpc-worker.php"
proto:
- "proto/helloworld.proto"
reload:
services:
grpc:
dirs: [ "." ]
recursive: true
patterns: [ ".proto", ".php" ]
Update docker-compose.yml
:
docker-compose.yml
services:
app:
ports:
- "51015:51015"
Update composer.json
autoload:
composer.json
"autoload": {
"psr-4": {
"App\\": "app/",
"GRPC\\": "generated/GRPC"
}
}
Create config/grpc.php
:
config/grpc.php
return [
'services' => [
__DIR__ . '/../app/Controllers/GRPC/**/*.php',
],
];
📐 Compiling Protobuf Files
Compile .proto
files:
make grpcgen proto/helloworld.proto
# or all:
make grpcgen proto/*.proto
Manual alternative:
docker-compose exec app protoc \
--plugin=protoc-gen-php-grpc \
--php_out=./generated \
--php-grpc_out=./generated \
proto/helloworld.proto
Without Docker:
protoc \
--plugin=protoc-gen-php-grpc \
--php_out=./generated \
--php-grpc_out=./generated \
proto/helloworld.proto
🚀 Example Service
syntax = "proto3";
option go_package = "proto/greeter";
option php_namespace = "GRPC\\Greeter";
option php_metadata_namespace = "GRPC\\GPBMetadata";
package helloworld;
// The greeting service definition.
service Greeter {
// Sends a greeting
rpc SayHello (HelloRequest) returns (HelloReply) {}
}
// The request message containing the user's name.
message HelloRequest {
string name = 1;
}
// The response message containing the greetings
message HelloReply {
string message = 1;
}
namespace App\Controllers\GRPC;
use GRPC\Greeter\GreeterInterface;
use GRPC\Greeter\HelloRequest;
use GRPC\Greeter\HelloReply;
use Beauty\GRPC\GrpcService;
use Spiral\RoadRunner\GRPC\ContextInterface;
#[GrpcService(GreeterInterface::class)]
class Greeter implements GreeterInterface
{
public function SayHello(ContextInterface $ctx, HelloRequest $in): HelloReply
{
return new HelloReply([
'message' => 'Hello ' . $in->getName(),
]);
}
}
All service implementations are auto-registered via #[GrpcService(...)]
attribute.
Worker: workers/grpc-worker.php
:
$server = new Server(new Invoker(), [ 'debug' => true ]);
$registry = new GrpcServiceRegistry($di, $server);
$registry->registerFromAttributes($grpcConfig['services']);
$server->serve(Worker::create());
🔗 Resources
- RoadRunner gRPC docs: https://docs.roadrunner.dev/docs/plugins/grpc
- Example app: https://github.com/beauty-framework/example-grpc
- This package repo: https://github.com/beauty-framework/grpc
📝 Notes
- Services are registered via
#[GrpcService(...)]
attribute - Implementations are auto-discovered from
app/Controllers/GRPC/**/*.php
- Generated classes live in
generated/
- You must recompile
.proto
files withmake grpcgen
after changes