bentools/pusher
Send Web Push notifications to multiple recipients across providers (Chrome/GCM, Mozilla) using async/parallel Guzzle requests. Supports multiple API keys, ping/notification/server messages, and per-recipient delivery reporting for unsubscribes. Unmaintained.
Installation
composer require bentools/pusher
Ensure guzzlehttp/guzzle (v6.x) is installed as a dependency.
Basic Configuration
Add service provider to config/app.php:
'providers' => [
// ...
Bentools\Pusher\PusherServiceProvider::class,
],
Publish config (optional):
php artisan vendor:publish --provider="Bentools\Pusher\PusherServiceProvider"
Configure config/pusher.php with API keys for GCM/Mozilla.
First Push
use Bentools\Pusher\Pusher;
use Bentools\Pusher\Message\TextMessage;
$pusher = app(Pusher::class);
$push = $pusher->createPush()
->addMessage(new TextMessage('Hello, world!'))
->addRecipient('user@example.com', 'GCM', ['endpoint' => '...', 'keys' => [...]]);
$pusher->push($push);
Pusher facade: Main service for creating and sending pushes.Push object: Central container for messages, recipients, and handlers.Message interfaces: Define payload structure (e.g., TextMessage, PingMessage).Handler classes: Abstract delivery logic (e.g., GcmHandler, MozillaHandler).Create a Push
$push = $pusher->createPush()
->addMessage($message)
->addRecipient($endpoint, $handlerType, $subscriptionData);
addMessage() for multiple payloads (e.g., text + data).Asynchronous Processing Leverage Guzzle’s async requests for bulk pushes:
$pushes = collect([$push1, $push2, $push3]);
$promises = $pushes->map(fn($push) => $pusher->push($push));
$results = Promise\all($promises);
Handler Chaining Route messages to multiple providers:
$push->addHandler('GCM', ['apiKey' => 'key1'])
->addHandler('Mozilla', ['apiKey' => 'key2']);
State Management Check push status post-delivery:
$push->getStatus(); // 'pending' | 'done'
$push->getFailedRecipients(); // Array of un delivered endpoints
PushJob::dispatch($push)->onQueue('push-notifications');
PushSent/PushFailed events for analytics:
event(new PushSent($push));
Push objects in a table (e.g., pushes) with JSON columns for recipients/handlers.| Scenario | Implementation |
|---|---|
| User-specific alerts | Attach recipient data to messages. |
| Bulk notifications | Use async handlers for parallel sends. |
| A/B testing | Route identical messages via different handlers. |
| Unsubscribe tracking | Log failedRecipients to a blacklist. |
Handler Configuration
$handler = $push->getHandler('GCM');
if (!$handler->isValid()) throw new \RuntimeException('Invalid GCM key');
Recipient Format
$endpoint = str_replace('https://', '', $endpoint);
Async Race Conditions
Promise\settle() for tracking individual failures:
$results = Promise\settle($promises);
foreach ($results as $result) {
if ($result['state'] === 'rejected') {
log($result['reason']);
}
}
Message Size Limits
$client = new \GuzzleHttp\Client(['handler' => \GuzzleHttp\HandlerStack::create()]);
$pusher->setHttpClient($client);
dd($push->getMessage(), $push->getRecipients(), $push->getHandlers());
Custom Handlers
Extend Bentools\Pusher\Handler\AbstractHandler:
class SlackHandler extends AbstractHandler {
protected function sendPush(Push $push): PromiseInterface {
return $this->httpClient->postAsync('https://slack.com/api/chat.postMessage', [
'json' => ['text' => $push->getMessage()->getContent()]
]);
}
}
Message Types
Implement Bentools\Pusher\Message\MessageInterface:
class JsonMessage implements MessageInterface {
public function getContent(): string {
return json_encode($this->data);
}
}
Middleware
Attach to Pusher for pre/post-processing:
$pusher->addMiddleware(function (Push $push) {
$push->addMetadata(['source' => 'laravel']);
});
$push->addHandler('GCM', ['apiKey' => 'key1'])
->addHandler('GCM', ['apiKey' => 'key2']);
spatie/laravel-webpush for Laravel-specific integrations.How can I help you explore Laravel packages today?