Installation:
composer require cmnty/push
Ensure ext-crypto or lib-openssl is installed for optimal performance.
First Use Case: Send a push notification to a user’s browser via a subscription endpoint:
use Cmnty\Push\Client;
use Cmnty\Push\AggregatePushService;
use Cmnty\Push\PushServiceRegistry;
use Cmnty\Push\GooglePushService;
use Cmnty\Push\Notification;
use Cmnty\Push\Subscription;
use Cmnty\Push\Endpoint;
use Cmnty\Push\PublicKey;
use Cmnty\Push\AuthenticationSecret;
// Initialize services
$pushServiceRegistry = new PushServiceRegistry();
$pushServiceRegistry->addPushService(new GooglePushService('YOUR_GOOGLE_API_KEY'));
$pushService = new AggregatePushService($pushServiceRegistry);
// Create client
$client = new Client($pushService);
// Define notification and subscription
$notification = new Notification('Hello', 'World!');
$subscription = new Subscription(
new Endpoint('https://fcm.googleapis.com/fcm/send/...'),
PublicKey::createFromBase64UrlEncodedString('PUBLIC_KEY'),
AuthenticationSecret::createFromBase64UrlEncodedString('AUTH_SECRET')
);
// Send push
$client->pushNotification($notification, $subscription);
Where to Look First:
Cmnty\Push\Client: Core class for sending notifications.Cmnty\Push\Crypto: For encryption fallback logic (if ext-crypto/lib-openssl fail).Service Registry:
Register multiple push services (e.g., Google FCM, Mozilla Push) in a single PushServiceRegistry to handle cross-platform notifications:
$pushServiceRegistry = new PushServiceRegistry();
$pushServiceRegistry->addPushService(new GooglePushService('API_KEY'));
$pushServiceRegistry->addPushService(new MozillaPushService());
$aggregateService = new AggregatePushService($pushServiceRegistry);
Encryption Strategy:
Use AggregateCrypt (default) for automatic fallback to ext-crypto → lib-openssl → spomky-labs/php-aes-gcm. Override if needed:
$client = new Client($pushService, null, new Cryptograph(new ExtCryptoCrypt()));
Notification Customization:
Extend Notification to add payload data (e.g., deep links, images):
$notification = new Notification('Title', 'Body', [
'data' => ['url' => '/dashboard', 'icon' => 'https://example.com/icon.png']
]);
Subscription Management:
Store subscriptions in a database (e.g., subscriptions table) and fetch them dynamically:
$subscription = Subscription::fromArray([
'endpoint' => 'https://...',
'keys' => [
'p256dh' => 'PUBLIC_KEY',
'auth' => 'AUTH_SECRET'
]
]);
User Opt-In Flow:
PushManager.subscribe().users table with subscription_data JSON column).Batch Processing:
Use AggregatePushService to send notifications to multiple subscriptions in a loop:
foreach ($userSubscriptions as $subscription) {
$client->pushNotification($notification, $subscription);
}
Error Handling:
Catch Cmnty\Push\Exception\PushException for failed sends (e.g., invalid keys, network issues):
try {
$client->pushNotification($notification, $subscription);
} catch (PushException $e) {
Log::error("Push failed: " . $e->getMessage());
// Retry or notify admin
}
Laravel Integration:
Client to the container in AppServiceProvider:
$this->app->singleton(Client::class, function ($app) {
$pushService = new AggregatePushService(
new PushServiceRegistry([
new GooglePushService(config('services.google_push.key'))
])
);
return new Client($pushService);
});
public function sendNotification(Client $client) {
$client->pushNotification($notification, $subscription);
}
Queue Push Jobs: Offload push notifications to a queue (e.g., Laravel Queues) to avoid blocking requests:
dispatch(new SendPushNotification($notification, $subscription));
Define the job:
class SendPushNotification implements ShouldQueue {
use Dispatchable, InteractsWithQueue, Queueable;
public function handle(Client $client) {
$client->pushNotification($this->notification, $this->subscription);
}
}
Testing:
Client in unit tests:
$mockClient = Mockery::mock(Client::class);
$mockClient->shouldReceive('pushNotification')->once();
GooglePushService with a dummy API key).Encryption Dependencies:
ext-crypto/lib-openssl: Falls back to spomky-labs/php-aes-gcm, which is slower. Install extensions for production:
pecl install crypto
or use lib-openssl (Linux: sudo apt-get install php-openssl).Key Validation:
PublicKey or AuthenticationSecret (e.g., malformed Base64URL) throws InvalidArgumentException. Validate keys before sending:
try {
PublicKey::createFromBase64UrlEncodedString($key);
} catch (InvalidArgumentException $e) {
// Handle error (e.g., log or reject subscription)
}
Rate Limiting:
$retryAfter = $e->getRetryAfter();
sleep($retryAfter);
CORS/HTTPS:
https:// and CORS headers are configured for the subscription endpoint.Deprecated Package:
minishlink/web-push for active maintenance.Enable Guzzle Debugging: Configure Guzzle to log HTTP requests/responses:
$client = new Client($pushService, new \GuzzleHttp\Client([
'debug' => fopen('guzzle.log', 'w'),
]));
Check Subscription Validity: Verify the subscription endpoint is active and keys are correct:
$subscription->getEndpoint()->isValid(); // Basic URL validation
Payload Inspection: Log the encrypted payload before sending to debug issues:
$payload = $client->getPushService()->createPayload($notification, $subscription);
Log::debug('Push payload:', [$payload]);
Google FCM API Key:
.env):
GOOGLE_PUSH_KEY=your_server_key_here
Mozilla Push:
Custom Cryptography:
Cmnty\Push\Crypto\Crypt for custom encryption (e.g., AWS KMS):
class AWSCrypt implements Crypt {
public function encrypt($data, $key) { /* ... */ }
public function decrypt($data, $key) { /* ... */ }
}
Then inject into Client:
$client = new Client($pushService, null, new Cryptograph(new AWSCrypt()));
Cmnty\Push\PushService for unsupported providers (e.g., Firebase Cloud Messaging v1):
class FirebaseV1PushService implements PushService {
public function createPayload(Notification $notification, Subscription $subscription) { /* ... */ }
public function sendPayload($payload, $endpoint) { /*
How can I help you explore Laravel packages today?