symfony/google-chat-notifier
Symfony Notifier integration for Google Chat. Configure a googlechat:// DSN with access key/token and target space, optionally providing a thread_key to group messages into a single thread.
Install the Package
composer require symfony/google-chat-notifier
For Laravel, ensure compatibility with Symfony’s Notifier component (v6+).
Configure the DSN
Add to .env:
GOOGLE_CHAT_DSN=googlechat://ACCESS_KEY:ACCESS_TOKEN@default/SPACE_NAME?thread_key=THREAD_ID
ACCESS_KEY/ACCESS_TOKEN with your Google Chat API credentials.SPACE_NAME is the Google Chat space ID (e.g., ABC123).thread_key (optional) groups messages into a thread.First Notification (Laravel)
Use Laravel’s Bus or Events to trigger a notification:
use Symfony\Component\Notifier\NotifierInterface;
use Symfony\Component\Notifier\Message\ChatMessage;
// In a Laravel service or event listener:
$notifier = app(NotifierInterface::class);
$notifier->send(new ChatMessage('Hello from Laravel!', (new ChatTransport())->withDsn(env('GOOGLE_CHAT_DSN'))));
First Notification (Symfony)
use Symfony\Component\Notifier\NotifierInterface;
use Symfony\Component\Notifier\Message\ChatMessage;
$notifier = new NotifierInterface([new GoogleChatTransport(env('GOOGLE_CHAT_DSN'))]);
$notifier->send(new ChatMessage('Hello from Symfony!'));
Create a Laravel Event
// Event
class DeploymentStarted implements ShouldBroadcast
{
public function broadcastOn(): array
{
return [new GoogleChatChannel()];
}
}
Broadcast the Event
// In a controller or job:
event(new DeploymentStarted('v1.2.0'));
Handle the Event with a Listener
use Symfony\Component\Notifier\Message\ChatMessage;
class GoogleChatDeploymentListener
{
public function handle(DeploymentStarted $event)
{
$notifier = app(NotifierInterface::class);
$notifier->send(new ChatMessage(
"Deployment started: {$event->version}",
(new GoogleChatTransport(env('GOOGLE_CHAT_DSN')))
->withOption('thread_key', 'deployments')
));
}
}
DSN Structure:
googlechat://ACCESS_KEY:ACCESS_TOKEN@default/SPACE_NAME?thread_key=THREAD_ID
default for the transport name if only one space is configured..env and switch dynamically:
$transport = new GoogleChatTransport(env('GOOGLE_CHAT_DSN_ONCALL'));
Dynamic Threading:
Use thread_key to group related messages (e.g., incident_123). Reset threads by omitting the key or using a new one.
Rich Cards: Leverage Google Chat’s card schema for interactive messages:
$message = new ChatMessage('Incident Alert!');
$message->card([
'header' => ['title' => 'Critical Issue'],
'sections' => [
['widgets' => [
['buttons' => [
['textButton' => ['text' => 'Acknowledge', 'onClick' => ['openLink' => 'https://jira.com/123']]],
]],
]],
],
]);
Attachments: Add files (e.g., logs, screenshots) via base64-encoded data or URLs:
$message->attachment('data:image/png;base64,' . base64_encode(file_get_contents('error.png')));
Events:
Use Laravel’s dispatch() to trigger notifications:
dispatch(new GoogleChatNotification('New user registered: ' . $user->email));
Queues: Queue notifications for async delivery:
GoogleChatNotification::dispatch($message)
->delay(now()->addMinutes(5))
->onQueue('notifications');
Tasks: Combine with Laravel Tasks for scheduled alerts:
Task::create()
->name('daily-metrics')
->everyMinute()
->run(function () {
$notifier = app(NotifierInterface::class);
$notifier->send(new ChatMessage('Daily metrics report', ...));
});
Dependency Injection:
Register the transport in services.yaml:
services:
Symfony\Component\Notifier\NotifierInterface:
arguments:
- ['@google_chat.transport']
google_chat.transport:
class: Symfony\Component\Notifier\Bridge\GoogleChat\GoogleChatTransport
arguments:
- '%env(GOOGLE_CHAT_DSN)%'
Messenger Component:
Use Symfony’s Messenger to handle notifications as messages:
use Symfony\Component\Messenger\MessageBusInterface;
$bus->dispatch(new ChatNotificationMessage('Hello from Messenger!'));
Mock the Transport:
$transport = $this->createMock(GoogleChatTransport::class);
$transport->method('send')->willReturn(true);
$notifier = new NotifierInterface([$transport]);
$notifier->send(new ChatMessage('Test'));
DSN Validation: Test DSN parsing in isolation:
$dsn = 'googlechat://key:token@default/space?thread_key=123';
$transport = new GoogleChatTransport($dsn);
$this->assertEquals('space', $transport->getSpace());
DSN Format Sensitivity:
@default in the DSN will throw InvalidArgumentException.if (!preg_match('/^googlechat:\/\/[^@]+@default\/[^?]+(\?[^#]*)?$/', $dsn)) {
throw new \InvalidArgumentException('Invalid Google Chat DSN format.');
}
Thread Key Handling:
thread_key is omitted, each message creates a new thread. Google Chat may rate-limit rapid thread creation.thread_key for grouped alerts (e.g., incidents) or regenerate it periodically.Authentication Expiry:
// Example: Refresh token via Google API client
$client = new Google_Client(['client_id' => 'YOUR_ID', 'client_secret' => 'YOUR_SECRET']);
$client->fetchAccessTokenWithRefreshToken($refreshToken);
Rate Limiting:
use Symfony\Component\HttpClient\RetryableHttpClient;
use Symfony\Contracts\HttpClient\RetryStrategyInterface;
$client = new RetryableHttpClient(
new RetryStrategyInterface(function (RetryableHttpClient $client, int $retries, int $maxRetries) {
return $retries < $maxRetries ? 1000 : 0; // Retry after 1s
})
);
Message Length Limits:
Enable HTTP Logging:
Configure Symfony’s HttpClient to log requests:
$client = HttpClient::create([
'headers' => ['User-Agent' => 'Laravel/GoogleChatNotifier'],
'debug' => true, // Logs requests to `var/log/http_client.log`
]);
Validate API Responses:
Check for Google Chat-specific errors (e.g., 403 Forbidden for invalid scopes):
try {
$response = $transport->send($message);
} catch (\Symfony\Contracts\HttpClient\Exception\ClientException
How can I help you explore Laravel packages today?