[PHP] WebPush
Step-by-step implementation of Web Push Notifications using plain PHP and the Minishlink/web-push library:
0. Install Composer in Windows
How to Install Composer in Windows, click this link
1. Install the Minishlink Web Push Library
Install the library using Composer:
composer require minishlink/web-push
2. Generate VAPID Keys
Use the library to generate the VAPID keys for authentication:
require 'vendor/autoload.php';
use Minishlink\WebPush\VAPID;
// Generate VAPID keys
$vapidKeys = VAPID::createVapidKeys();
echo 'Public Key: ' . $vapidKeys['publicKey'] . PHP_EOL;
echo 'Private Key: ' . $vapidKeys['privateKey'] . PHP_EOL;
Save the Public Key
and Private Key
for use in the frontend and backend.
3. Create the Subscription Storage
Store user subscriptions in a database.
Example Table:
CREATE TABLE push_subscriptions (
id INT AUTO_INCREMENT PRIMARY KEY,
endpoint TEXT NOT NULL,
public_key TEXT NOT NULL,
auth_key TEXT NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
4. Create an Endpoint to Save Subscriptions
Create a PHP script (subscribe.php
) to save subscription data sent by the browser.
subscribe.php
:
<?php
require 'vendor/autoload.php';
// Database connection
$dsn = 'mysql:host=localhost;dbname=your_database;charset=utf8';
$username = 'your_username';
$password = 'your_password';
try {
$pdo = new PDO($dsn, $username, $password);
} catch (PDOException $e) {
die('Database connection failed: ' . $e->getMessage());
}
// Retrieve subscription data from the request
$data = json_decode(file_get_contents('php://input'), true);
$endpoint = $data['endpoint'];
$publicKey = $data['keys']['p256dh'];
$authKey = $data['keys']['auth'];
// Store subscription in the database
$stmt = $pdo->prepare("INSERT INTO push_subscriptions (endpoint, public_key, auth_key) VALUES (?, ?, ?)");
$stmt->execute([$endpoint, $publicKey, $authKey]);
echo json_encode(['success' => true]);
5. Create a Script to Send Notifications
Create a PHP script (send_notification.php
) to send notifications to all subscribers.
send_notification.php
:
<?php
require 'vendor/autoload.php';
use Minishlink\WebPush\WebPush;
use Minishlink\WebPush\Subscription;
// Database connection
$dsn = 'mysql:host=localhost;dbname=your_database;charset=utf8';
$username = 'your_username';
$password = 'your_password';
try {
$pdo = new PDO($dsn, $username, $password);
} catch (PDOException $e) {
die('Database connection failed: ' . $e->getMessage());
}
// Retrieve all subscriptions
$stmt = $pdo->query("SELECT * FROM push_subscriptions");
$subscriptions = $stmt->fetchAll(PDO::FETCH_ASSOC);
// VAPID keys
$vapid = [
'subject' => 'mailto:example@example.com',
'publicKey' => 'YOUR_PUBLIC_KEY',
'privateKey' => 'YOUR_PRIVATE_KEY',
];
// WebPush instance
$webPush = new WebPush(['VAPID' => $vapid]);
// Notification payload
$payload = json_encode([
'title' => 'Reminder',
'body' => 'You have a new task to complete!',
]);
// Send notifications
foreach ($subscriptions as $subscription) {
$webPush->sendNotification(
Subscription::create([
'endpoint' => $subscription['endpoint'],
'publicKey' => $subscription['public_key'],
'authToken' => $subscription['auth_key'],
]),
$payload
);
}
// Flush notifications
foreach ($webPush->flush() as $report) {
if (!$report->isSuccess()) {
echo "Push failed: {$report->getReason()} for endpoint: {$report->getEndpoint()}\n";
}
}
6. Frontend Implementation
Register a Service Worker
Create a sw.js
file in the public directory to handle incoming push notifications.
self.addEventListener('push', event => {
const data = event.data.json();
self.registration.showNotification(data.title, {
body: data.body,
icon: '/icon.png', // Optional
});
});
Subscribe to Push Notifications
Add JavaScript to your frontend to subscribe users to push notifications.
<script>
const publicKey = 'YOUR_PUBLIC_KEY'; // Replace with your VAPID public key
// Convert VAPID public key to Uint8Array
function urlBase64ToUint8Array(base64String) {
const padding = '='.repeat((4 - base64String.length % 4) % 4);
const base64 = (base64String + padding).replace(/-/g, '+').replace(/_/g, '/');
const rawData = window.atob(base64);
return Uint8Array.from([...rawData].map((char) => char.charCodeAt(0)));
}
// Register the service worker
navigator.serviceWorker.register('/sw.js').then(registration => {
// Subscribe the user to push
return registration.pushManager.subscribe({
userVisibleOnly: true,
applicationServerKey: urlBase64ToUint8Array(publicKey),
});
}).then(subscription => {
// Send subscription data to the server
return fetch('/subscribe.php', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(subscription),
});
}).then(() => {
console.log('Subscribed to push notifications!');
}).catch(err => {
console.error('Failed to subscribe:', err);
});
</script>
7. Test Your Implementation
- Serve your application over HTTPS (required for the Push API).
- Open the page in a browser and subscribe to push notifications.
- Trigger
send_notification.php
to send a push notification.
No Comments