PHP (Laravel) + gRPC
gRPC (Google Remote Procedure Call) is a modern communication framework for services. It uses HTTP/2 and Protocol Buffers (Protobuf). It is fast, supports streaming, and is great for distributed systems. In this post, you will learn how to set up gRPC in a Laravel project and create a full account registration service with validation, controller, model, service, and tests. Why Use gRPC with Laravel ? Even though Laravel is usually used with REST APIs, using gRPC brings several benefits: Speed: faster communication between services. Multi-language support: perfect for microservices in different languages. Strong contract: with Protobuf, you get strong typing and validation. Installing RoadRunner We will use RoadRunner as the application server to handle gRPC. composer require spiral/roadrunner Defining the Proto Contract Create a file called proto/user.proto: syntax = "proto3"; package user; service UserService { rpc CreateUser (CreateUserRequest) returns (CreateUserResponse); } message CreateUserRequest { string name = 1; string email = 2; string password = 3; } message CreateUserResponse { string message = 1; } Generating PHP files Use protoc to generate PHP classes from the .proto file: protoc \ --proto_path=proto \ --php_out=app/Grpc \ --grpc_out=app/Grpc \ --plugin=protoc-gen-grpc=/usr/local/bin/grpc_php_plugin \ proto/user.proto Creating Laravel Application Files

gRPC (Google Remote Procedure Call) is a modern communication framework for services. It uses HTTP/2 and Protocol Buffers (Protobuf). It is fast, supports streaming, and is great for distributed systems. In this post, you will learn how to set up gRPC in a Laravel project and create a full account registration service with validation, controller, model, service, and tests.
Why Use gRPC with Laravel ?
Even though Laravel is usually used with REST APIs, using gRPC brings several benefits:
Speed: faster communication between services.
Multi-language support: perfect for microservices in different languages.
Strong contract: with Protobuf, you get strong typing and validation.
Installing RoadRunner
We will use RoadRunner as the application server to handle gRPC.
composer require spiral/roadrunner
Defining the Proto Contract
Create a file called proto/user.proto
:
syntax = "proto3";
package user;
service UserService {
rpc CreateUser (CreateUserRequest) returns (CreateUserResponse);
}
message CreateUserRequest {
string name = 1;
string email = 2;
string password = 3;
}
message CreateUserResponse {
string message = 1;
}
Generating PHP files
Use protoc
to generate PHP classes from the .proto
file:
protoc \
--proto_path=proto \
--php_out=app/Grpc \
--grpc_out=app/Grpc \
--plugin=protoc-gen-grpc=/usr/local/bin/grpc_php_plugin \
proto/user.proto
Creating Laravel Application Files
// app/Models/User.php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
class User extends Authenticatable
{
use HasFactory, Notifiable;
protected $fillable = [
'name', 'email', 'password'
];
protected $hidden = [
'password', 'remember_token'
];
}
gRPC Controller
// app/Grpc/UserService.php
namespace App\Grpc;
use User\CreateUserRequest;
use User\CreateUserResponse;
use User\UserServiceInterface;
use App\Services\UserService as LocalUserService;
use Illuminate\Support\Facades\Validator;
class UserService implements UserServiceInterface
{
public function __construct(
protected LocalUserService $service
) {}
public function CreateUser(CreateUserRequest $request): CreateUserResponse
{
$data = [
'name' => $request->getName(),
'email' => $request->getEmail(),
'password' => $request->getPassword(),
];
$validator = Validator::make($data, [
'name' => 'required|string|max:255',
'email' => 'required|email|unique:users,email',
'password' => 'required|string|min:6',
]);
if ($validator->fails()) {
throw new \Exception($validator->errors()->first());
}
$user = User::create([
'name' => $data['name'],
'email' => $data['email'],
'password' => Hash::make($data['password']),
]);
$response = new CreateUserResponse();
$response->setMessage("User {$user->name} created successfully!");
return $response;
}
}
Run gRPC Server
// grpc.php
use Spiral\RoadRunner\GRPC\Server;
use App\Grpc\UserService;
require 'vendor/autoload.php';
$server = new Server();
$server->registerService(UserService::class);
$server->serve();
Testing with a gRPC Client(PHP)
$client = new \User\UserServiceClient('127.0.0.1:9000', [
'credentials' => \Grpc\ChannelCredentials::createInsecure()
]);
$request = new \User\CreateUserRequest();
$request->setName('John Doe');
$request->setEmail('john@example.com');
$request->setPassword('secret');
[$response, $status] = $client->CreateUser($request)->wait();
echo $response->getMessage();
Create a Testing
- Install pest
composer require pestphp/pest --dev
Create the Test
// tests/Feature/Grpc/CreateUserTest.php
use User\UserServiceClient;
use User\CreateUserRequest;
use Grpc\ChannelCredentials;
test('should create a user using gRPC', function () {
$client = new UserServiceClient('127.0.0.1:9000', [
'credentials' => ChannelCredentials::createInsecure()
]);
$request = new CreateUserRequest();
$request->setName('Maria Test');
$request->setEmail('maria.test@example.com');
$request->setPassword('12345678');
[$response, $status] = $client->CreateUser($request)->wait();
expect($status->code)->toBe(0); // OK
expect($response->getMessage())->toContain('Maria Test');
});
Run your tests with:
./vendor/bin/pest
Make sure your gRPC server is running before executing the test.
Conclusion
With this complete example using Laravel, we created a gRPC service that includes everything: Model, Service, validation, Protobuf integration, and automated testing with Pest. This structure is perfect for scalable, fast, and distributed applications, especially in systems where services use different technologies.
To learn more about gRPC with PHP and RoadRunner, check these docs and articles: