google/cloud-pubsub
Idiomatic PHP client for Google Cloud Pub/Sub. Publish and receive messages between services using REST or gRPC (including streaming). Install via Composer and authenticate with Google Cloud credentials for managed, real-time messaging.
Installation:
composer require google/cloud-pubsub
Ensure your Laravel project uses PHP 8.1+ (recommended) for full compatibility.
Authentication:
Configure credentials via environment variables (recommended) or Laravel's .env:
GOOGLE_APPLICATION_CREDENTIALS=/path/to/service-account.json
Or use the GOOGLE_CLOUD_PROJECT environment variable for ADC (Application Default Credentials).
First Use Case: Publish a message to a topic:
use Google\Cloud\PubSub\V1\PublisherClient;
use Google\Cloud\PubSub\V1\TopicName;
$publisher = new PublisherClient();
$topic = $publisher->topicName('your-project-id', 'your-topic-name');
$future = $publisher->publish($topic, ['data' => 'Hello Pub/Sub!']);
$messageId = $future->wait();
PublisherClient for sending messages.SubscriberClient for pulling messages (with streaming support).TopicAdminClient/SubscriptionAdminClient for managing resources.BatchingPublisherClient for optimized bulk publishing.$future = $publisher->publish($topic, ['data' => json_encode($payload)]);
$messageId = $future->wait(); // Blocks until published
$future = $publisher->publish($topic, ['data' => $payload]);
$future->then(function ($messageId) {
Log::info("Published message ID: $messageId");
});
$batchSettings = new \Google\Cloud\PubSub\V1\BatchingSettings();
$batchSettings->setElementCountLimit(100);
$batchSettings->setDelayThreshold(\Google\Protobuf\Duration::fromSeconds(1));
$batchPublisher = new \Google\Cloud\PubSub\V1\BatchingPublisherClient($batchSettings);
$future = $batchPublisher->publish($topic, ['data' => $payload]);
$subscriber = new \Google\Cloud\PubSub\V1\SubscriberClient();
$subscription = $subscriber->subscriptionName('project-id', 'sub-name');
$response = $subscriber->pull($subscription, ['maxMessages' => 10]);
foreach ($response->getReceivedMessages() as $receivedMessage) {
$message = $receivedMessage->getMessage();
// Process message
$subscriber->acknowledge($subscription, [$receivedMessage]);
}
$stream = $subscriber->streamingPull($subscription);
foreach ($stream as $batch) {
foreach ($batch->getReceivedMessages() as $receivedMessage) {
$message = $receivedMessage->getMessage();
// Process message
$subscriber->acknowledge($subscription, [$receivedMessage]);
}
}
Tip: Use Laravel's queue:work process manager to handle streaming subscribers.$topicAdmin = new \Google\Cloud\PubSub\V1\TopicAdminClient();
$topic = $topicAdmin->createTopic('project-id', 'new-topic');
$subscriptionAdmin = new \Google\Cloud\PubSub\V1\SubscriptionAdminClient();
$subscription = $subscriptionAdmin->createSubscription(
'project-id',
'sub-name',
'projects/project-id/topics/topic-name'
);
$transform = new \Google\Cloud\PubSub\V1\MessageTransform();
$transform->setEnabled(true);
$transform->setSchema('projects/project-id/schemas/schema-name');
$subscription = $subscriptionAdmin->createSubscription(
'project-id',
'sub-name',
'projects/project-id/topics/topic-name',
['messageTransform' => $transform]
);
Service Provider:
Bind the client to Laravel's container in AppServiceProvider:
public function register()
{
$this->app->singleton(\Google\Cloud\PubSub\V1\PublisherClient::class, function ($app) {
return new \Google\Cloud\PubSub\V1\PublisherClient();
});
}
Queued Jobs: Use Laravel Queues to process Pub/Sub messages asynchronously:
class ProcessPubSubMessage implements ShouldQueue
{
public function handle()
{
$subscriber = resolve(\Google\Cloud\PubSub\V1\SubscriberClient::class);
$subscription = $subscriber->subscriptionName('project-id', 'sub-name');
$response = $subscriber->pull($subscription, ['maxMessages' => 1]);
if ($response->getReceivedMessages()) {
$this->dispatch(new ProcessMessageJob($response->getReceivedMessages()[0]));
}
}
}
Event Dispatching: Trigger Laravel events from Pub/Sub messages:
$subscriber->pull($subscription, ['maxMessages' => 10])->then(function ($response) {
foreach ($response->getReceivedMessages() as $receivedMessage) {
event(new PubSubMessageReceived($receivedMessage->getMessage()));
$subscriber->acknowledge($subscription, [$receivedMessage]);
}
});
Retry Logic: Implement exponential backoff for failed operations:
use Google\ApiCore\ApiException;
use Symfony\Component\Process\Exception\ProcessFailedException;
try {
$future = $publisher->publish($topic, ['data' => $payload]);
$future->wait();
} catch (ApiException $e) {
if ($e->getStatus()->getCode() === 5) { // Retry on unavailable
throw new ProcessFailedException($e);
}
throw $e;
}
Authentication Issues:
Google\Auth\Exception\GoogleAuthException: Could not load credentials.GOOGLE_APPLICATION_CREDENTIALS is set or use ADC. Verify the service account has roles/pubsub.publisher/roles/pubsub.subscriber.env() helper to load credentials dynamically:
putenv('GOOGLE_APPLICATION_CREDENTIALS=' . env('GOOGLE_CREDENTIALS_PATH'));
Message Size Limits:
Streaming Pull Timeouts:
$stream = $subscriber->streamingPull($subscription, [
'request' => new \Google\Cloud\PubSub\V1\StreamingPullRequest([
'maxMessages' => 100,
'returnImmediately' => false,
])
]);
queue:listen --daemon) to avoid HTTP timeout issues.Message Ordering:
$future = $publisher->publish($topic, [
'data' => $payload,
'orderingKey' => 'user-' . $userId
]);
Deprecated Options:
keyFile/keyFilePath in client options (deprecated in v2.15.0). Use environment variables or ADC instead.Enable Debug Logging:
$client = new \Google\Cloud\PubSub\V1\PublisherClient([
'logger' => new \Monolog\Logger('pubsub', [
new \Monolog\Handler\StreamHandler(storage_path('logs/pubsub.log'), \Monolog\Logger::DEBUG),
]),
]);
Inspect API Responses:
serializeToJsonString() to debug complex responses:
How can I help you explore Laravel packages today?