google/grpc-gcp
GCP-specific extensions for gRPC, providing components and tooling to enhance gRPC clients when accessing Google Cloud APIs. Includes source for extensions plus infrastructure for end-to-end tests and benchmarks for cloud API access.
Install Dependencies:
# On Ubuntu/Debian
sudo apt-get install build-essential autoconf libtool pkg-config php php-dev
curl -sS https://getcomposer.org/installer | php
sudo mv composer.phar /usr/local/bin/composer
Install gRPC-PHP Extensions:
sudo pecl install protobuf grpc
Add to php.ini:
extension=grpc.so
extension=protobuf.so
Generate Protobuf Classes: Clone the googleapis repo and generate PHP classes:
git clone https://github.com/googleapis/googleapis.git
cd googleapis
make LANGUAGE=php OUTPUT=./generated
Move generated files to your Laravel project (e.g., app/Generated/Google).
Set Up Laravel Service Provider:
Create a provider (e.g., app/Providers/GcpGrpcServiceProvider.php):
use Google\Auth\ApplicationDefaultCredentials;
use Grpc\ChannelCredentials;
class GcpGrpcServiceProvider extends ServiceProvider
{
public function register()
{
$credentials = ApplicationDefaultCredentials::getCredentials();
$sslCreds = ChannelCredentials::createSsl();
$this->app->singleton('grpc.channel', function () use ($sslCreds, $credentials) {
return new \Grpc\Channel(
'firestore.googleapis.com',
[
'credentials' => $sslCreds,
'update_metadata' => $credentials->getUpdateMetadataFunc(),
]
);
});
}
}
First gRPC Call in Laravel:
use Google\Cloud\Firestore\V1beta1\FirestoreClient;
use Google\Cloud\Firestore\V1beta1\ListDocumentsRequest;
public function listFirestoreDocuments()
{
$channel = app('grpc.channel');
$client = new FirestoreClient($channel);
$request = new ListDocumentsRequest();
$request->setParent("projects/{PROJECT_ID}/databases/(default)/documents");
$response = $client->ListDocuments($request)->wait();
return $response->getDocuments();
}
Configure Credentials:
Set the GOOGLE_APPLICATION_CREDENTIALS environment variable in .env:
GOOGLE_APPLICATION_CREDENTIALS=/path/to/your/service-account.json
Leverage Laravel’s service providers to centralize gRPC client initialization:
// app/Providers/GcpGrpcServiceProvider.php
public function register()
{
$this->app->bind('firestore.client', function () {
$channel = $this->app->make('grpc.channel');
return new \Google\Cloud\Firestore\V1beta1\FirestoreClient($channel);
});
}
Usage:
$documents = app('firestore.client')->ListDocuments($request)->wait();
Create repositories to abstract gRPC calls (e.g., FirestoreRepository):
class FirestoreRepository
{
protected $client;
public function __construct(FirestoreClient $client)
{
$this->client = $client;
}
public function getDocument(string $documentPath): ?Document
{
$request = new GetDocumentRequest();
$request->setName($documentPath);
$response = $this->client->GetDocument($request)->wait();
return $response->getDocument() ?? null;
}
}
Register in AppServiceProvider:
$this->app->bind(FirestoreRepository::class, function ($app) {
return new FirestoreRepository($app->make('firestore.client'));
});
Handle gRPC streaming (e.g., Pub/Sub subscriptions) with Laravel events or queues:
// Subscribe to Pub/Sub stream
$stream = $pubSubClient->Pull($request);
$stream->onReceive(function ($message) {
event(new PubSubMessageReceived($message));
});
Listen in Laravel:
Event::listen(PubSubMessageReceived::class, function ($event) {
dispatch(new ProcessPubSubMessage($event->message));
});
Map gRPC responses to Laravel models or collections:
public function syncFirestoreToLocal()
{
$documents = app('firestore.client')->ListDocuments($request)->wait();
return collect($documents->getDocuments())
->map(fn ($doc) => new LocalDocumentModel([
'id' => $doc->getName(),
'data' => $doc->getFields(),
]));
}
Wrap gRPC calls in Laravel exceptions:
public function safeGrpcCall(callable $callback)
{
try {
return $callback();
} catch (\Grpc\RpcException $e) {
throw new GcpGrpcException(
"gRPC Error: {$e->getCode()}: {$e->getMessage()}",
$e->getCode(),
$e
);
}
}
Use Laravel’s config system for gRPC settings:
// config/gcp.php
return [
'services' => [
'firestore' => [
'project_id' => env('GCP_FIRESTORE_PROJECT_ID'),
'database' => '(default)',
],
],
];
Access in code:
$projectId = config('gcp.services.firestore.project_id');
Use Google\Cloud\Testing\MockGrpc for unit tests:
public function testFirestoreListDocuments()
{
$mock = new MockFirestoreClient();
$mock->expects($this)
->method('ListDocuments')
->willReturn(new ListDocumentsResponse());
$repository = new FirestoreRepository($mock);
$this->assertNotNull($repository->getDocument('test-path'));
}
Protobuf Generation Issues:
.proto files cause compilation errors.make LANGUAGE=php script from googleapis to auto-resolve dependencies.vendor/google/protobuf to avoid version conflicts.Credential Management:
ApplicationDefaultCredentials fails silently if GOOGLE_APPLICATION_CREDENTIALS is misconfigured.$credentials = ApplicationDefaultCredentials::getCredentials();
if (!$credentials) {
throw new RuntimeException("GCP credentials not found. Set GOOGLE_APPLICATION_CREDENTIALS.");
}
Shared Memory Leaks:
google/grpc-gcp:^0.4.0 (fixed in v0.1.2+) and ensure processes are short-lived or use pcntl_fork() for workers.PHP 8.x Compatibility:
google/cloud SDKs.composer.json:
"require": {
"protobuf/php": "^5.0",
"google/cloud-firestore": "^1.0"
}
TLS Certificate Validation:
$sslCreds = ChannelCredentials::createSsl([
'ca_file' => '/path/to/custom-ca.pem',
]);
Streaming Timeouts:
$stream->onReceive(function ($message) {
ProcessPubSubMessage::dispatch($message);
});
Protobuf Serialization:
Serializable or use google/protobuf:^3.21 for backward compatibility.Enable gRPC Logging:
Add to php.ini:
grpc.verbose_logging = 1
Check logs at /var/log/php-grpc.log.
Inspect Metadata: Log gRPC metadata for debugging:
$metadata = $response->getTrailingMetadata();
\Log::debug('gRPC Metadata:', $metadata->toArray());
3
How can I help you explore Laravel packages today?