bentools/webpush-bundle
Symfony bundle to send Web Push notifications using the Web Push protocol. Manage user-to-subscription associations (multi-device and shared devices) with your own persistence (Doctrine or custom). Includes VAPID key generation and backend APIs for subscriptions.
UserSubscriptionManagerRegistry, PushMessageSender).webpush-client. This is a strong fit for any PHP app needing push notifications.UserSubscription entity, UserSubscriptionManagerInterface), making it adaptable to custom persistence (e.g., Laravel’s Eloquent) with minimal refactoring.UserInterface, EventDispatcher, Doctrine (optional but recommended). Laravel equivalents exist but require mapping (e.g., Illuminate\Contracts\Auth\Authenticatable → UserInterface).minishlink/web-push (PHP Web Push library), which is Laravel-compatible. Key generation (webpush:generate:keys) can be replicated via custom Artisan commands.webpush-client (JavaScript) for subscription handling. No Laravel-specific changes needed here.UserSubscriptionManagerRegistry would need a Laravel equivalent (e.g., a facade or service container binding)./webpush endpoint must be mapped to Laravel’s routing system (e.g., Route::post('/webpush', ...)).EventDispatcher → Laravel’s Events or Listeners.UserSubscriptionManagerRegistry and PushMessageSender introduces refactoring risk. A Laravel port would require rewriting these as custom services.UserSubscription entity assumes Doctrine annotations. Laravel’s Eloquent or custom attribute mappings would need adjustment.LaravelWebPushManager implementing UserSubscriptionManagerInterface).minishlink/web-push library directly if bundle integration proves too cumbersome.UserSubscriptionManagerRegistry and PushMessageSender into Laravel-compatible services?/webpush endpoint in Laravel’s routing system?
minishlink/web-push directly with Laravel’s queue system for notifications?webpush:generate:keys as an Artisan command?minishlink/web-push) is Laravel-compatible. Focus on abstracting Symfony-specific components.UserSubscription entity with minimal changes (e.g., use Illuminate\Database\Eloquent\Model).EventDispatcher with Laravel’s Events or Listeners./webpush route to Laravel’s Route::post('/webpush', ...) with a custom controller.webpush-client works agnostically of the backend framework.Phase 1: Dependency Setup
composer require bentools/webpush-bundle
webpush:generate:keys):
// app/Console/Commands/GenerateVapidKeys.php
use minishlink\webpush\Vapid;
public function handle() {
$vapid = new Vapid();
$this->info("Public Key: " . $vapid->getPublicKey());
$this->info("Private Key: " . $vapid->getPrivateKey());
}
.env:
WEB_PUSH_PUBLIC_KEY=...
WEB_PUSH_PRIVATE_KEY=...
Phase 2: Entity & Manager Abstraction
UserSubscription model:
// app/Models/UserSubscription.php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use BenTools\WebPushBundle\Model\Subscription\UserSubscriptionInterface;
class UserSubscription extends Model implements UserSubscriptionInterface {
// Implement required methods (getUser(), getEndpoint(), etc.)
}
UserSubscriptionManager:
// app/Services/LaravelUserSubscriptionManager.php
namespace App\Services;
use App\Models\UserSubscription;
use BenTools\WebPushBundle\Model\Subscription\UserSubscriptionManagerInterface;
use Illuminate\Support\Facades\Hash;
class LaravelUserSubscriptionManager implements UserSubscriptionManagerInterface {
public function hash(string $endpoint, $user): string {
return Hash::make($endpoint);
}
// Implement other methods using Eloquent...
}
AppServiceProvider):
$this->app->bind(
\BenTools\WebPushBundle\Model\Subscription\UserSubscriptionManagerInterface::class,
\App\Services\LaravelUserSubscriptionManager::class
);
Phase 3: Routing & Endpoint
routes/web.php:
Route::post('/webpush', [WebPushController::class, 'handleSubscription']);
// app/Http/Controllers/WebPushController.php
use BenTools\WebPushBundle\WebPushEvents;
use Illuminate\Http\Request;
class WebPushController {
public function handleSubscription(Request $request) {
// Parse subscription data and dispatch Symfony-like events
event(new WebPushEvents($request->input()));
}
}
Phase 4: Notification Dispatch
PushMessageSender with a Laravel service:
// app/Services/LaravelPushMessageSender.php
use minishlink\webpush\WebPush;
class LaravelPushMessageSender {
public function send(PushNotification $notification) {
$webPush = new WebPush(
env('WEB_PUSH_PUBLIC_KEY'),
env('WEB_PUSH_PRIVATE_KEY'),
env('WEB_PUSH_SUBJECT', request()->getHost())
);
$webPush->sendNotification($notification->getSubscription(), $notification->getPayload());
}
}
AppServiceProvider:
$this->app->bind(
\BenTools\WebPushBundle\Sender\PushMessageSender::class,
\App\Services\LaravelPushMessageSender::class
);
Phase 5: Event Listeners
// app/Listeners/NotifyOnOrderPlaced.php
use App\Events\OrderPlaced;
use BenTools\WebPushBundle\Model\Subscription\UserSubscriptionManagerRegistry;
class NotifyOnOrderPlaced {
public function handle(OrderPlaced $event) {
$sender = app(PushMessageSender::class);
$sender->send(new PushNotification($event->order->customer->subscriptions, "Order placed!"));
}
}
EventServiceProvider:
protected $listen = [
OrderPlaced::class => [NotifyOnOrderPlaced::class],
];
How can I help you explore Laravel packages today?