{"id":329112,"date":"2021-08-23T13:00:59","date_gmt":"2021-08-23T10:00:59","guid":{"rendered":"https:\/\/en.buradabiliyorum.com\/how-to-send-web-push-notifications-with-php-cloudsavvy-it\/"},"modified":"2021-08-23T13:00:59","modified_gmt":"2021-08-23T10:00:59","slug":"how-to-send-web-push-notifications-with-php-cloudsavvy-it","status":"publish","type":"post","link":"https:\/\/buradabiliyorum.com\/en\/how-to-send-web-push-notifications-with-php-cloudsavvy-it\/","title":{"rendered":"#How to Send Web Push Notifications With PHP \u2013 CloudSavvy IT"},"content":{"rendered":"<div id=\"ez-toc-container\" class=\"ez-toc-v2_0_84 counter-hierarchy ez-toc-counter ez-toc-custom ez-toc-container-direction\">\n<p class=\"ez-toc-title\" style=\"cursor:inherit\">Table of Contents<\/p>\n<label for=\"ez-toc-cssicon-toggle-item-6a2d2b1f17308\" class=\"ez-toc-cssicon-toggle-label\"><span class=\"\"><span class=\"eztoc-hide\" style=\"display:none;\">Toggle<\/span><span class=\"ez-toc-icon-toggle-span\"><svg style=\"fill: #dd3333;color:#dd3333\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" class=\"list-377408\" width=\"20px\" height=\"20px\" viewBox=\"0 0 24 24\" fill=\"none\"><path d=\"M6 6H4v2h2V6zm14 0H8v2h12V6zM4 11h2v2H4v-2zm16 0H8v2h12v-2zM4 16h2v2H4v-2zm16 0H8v2h12v-2z\" fill=\"currentColor\"><\/path><\/svg><svg style=\"fill: #dd3333;color:#dd3333\" class=\"arrow-unsorted-368013\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"10px\" height=\"10px\" viewBox=\"0 0 24 24\" version=\"1.2\" baseProfile=\"tiny\"><path d=\"M18.2 9.3l-6.2-6.3-6.2 6.3c-.2.2-.3.4-.3.7s.1.5.3.7c.2.2.4.3.7.3h11c.3 0 .5-.1.7-.3.2-.2.3-.5.3-.7s-.1-.5-.3-.7zM5.8 14.7l6.2 6.3 6.2-6.3c.2-.2.3-.5.3-.7s-.1-.5-.3-.7c-.2-.2-.4-.3-.7-.3h-11c-.3 0-.5.1-.7.3-.2.2-.3.5-.3.7s.1.5.3.7z\"\/><\/svg><\/span><\/span><\/label><input type=\"checkbox\"  id=\"ez-toc-cssicon-toggle-item-6a2d2b1f17308\" checked aria-label=\"Toggle\" \/><nav><ul class='ez-toc-list ez-toc-list-level-1 ' ><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-1\" href=\"https:\/\/buradabiliyorum.com\/en\/how-to-send-web-push-notifications-with-php-cloudsavvy-it\/#Prerequisites\" >Prerequisites<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-2\" href=\"https:\/\/buradabiliyorum.com\/en\/how-to-send-web-push-notifications-with-php-cloudsavvy-it\/#Getting_Setup\" >Getting Setup<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-3\" href=\"https:\/\/buradabiliyorum.com\/en\/how-to-send-web-push-notifications-with-php-cloudsavvy-it\/#Providing_VAPID_Keys\" >Providing VAPID Keys<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-4\" href=\"https:\/\/buradabiliyorum.com\/en\/how-to-send-web-push-notifications-with-php-cloudsavvy-it\/#Registering_Push_Subscriptions\" >Registering Push Subscriptions<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-5\" href=\"https:\/\/buradabiliyorum.com\/en\/how-to-send-web-push-notifications-with-php-cloudsavvy-it\/#Preparing_Subscriptions\" >Preparing Subscriptions<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-6\" href=\"https:\/\/buradabiliyorum.com\/en\/how-to-send-web-push-notifications-with-php-cloudsavvy-it\/#Sending_a_Notification\" >Sending a Notification<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-7\" href=\"https:\/\/buradabiliyorum.com\/en\/how-to-send-web-push-notifications-with-php-cloudsavvy-it\/#Batching_Notifications\" >Batching Notifications<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-8\" href=\"https:\/\/buradabiliyorum.com\/en\/how-to-send-web-push-notifications-with-php-cloudsavvy-it\/#Notification_Options\" >Notification Options<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-9\" href=\"https:\/\/buradabiliyorum.com\/en\/how-to-send-web-push-notifications-with-php-cloudsavvy-it\/#Summary\" >Summary<\/a><\/li><\/ul><\/nav><\/div>\n<p><strong>&#8220;#How to Send Web Push Notifications With PHP \u2013 CloudSavvy IT&#8221;<\/strong><\/p>\n<div id=\"article-content-area\">\n<img loading=\"lazy\" decoding=\"async\" class=\"type:primaryImage aligncenter size-full wp-image-4047\" srcset=\"https:\/\/www.cloudsavvyit.com\/p\/uploads\/2017\/08\/1ac500da.png?width=398&amp;trim=1,1&amp;bg-color=000&amp;pad=1,1 400w, https:\/\/www.cloudsavvyit.com\/p\/uploads\/2017\/08\/1ac500da.png?width=1198&amp;trim=1,1&amp;bg-color=000&amp;pad=1,1 1200w\" sizes=\"auto, 400w, 1200w\" src=\"https:\/\/www.cloudsavvyit.com\/p\/uploads\/2017\/08\/1ac500da.png?width=1198&amp;trim=1,1&amp;bg-color=000&amp;pad=1,1\" alt=\"PHP Logo\" width=\"1400\" height=\"600\" onload=\"pagespeed.lazyLoadImages.loadIfVisibleAndMaybeBeacon(this);\" onerror=\"this.onerror=null;pagespeed.lazyLoadImages.loadIfVisibleAndMaybeBeacon(this);\"\/><\/p>\n<p>The Web Push API lets you send push notifications to web browsers and APIs. While most of the logic h<a href=\"https:\/\/buradabiliyorum.com\/en\/category\/download-scripts-themes-apps\/\" data-internallinksmanager029f6b8e52c=\"9\" title=\"Download Scripts &amp; Themes &amp; Apps\" target=\"_blank\" rel=\"noopener\">app<\/a>ens in the browser, you still need a server-side component to generate your notifications. Here\u2019s how to implement a Web Push backend using PHP.<\/p>\n<h2 id=\"prerequisites\"><span class=\"ez-toc-section\" id=\"Prerequisites\"><\/span>Prerequisites<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>For the purposes of this tutorial, we\u2019ll assume you\u2019re familiar with the basics of creating HTTP APIs in PHP. You\u2019ll need to expose a few public endpoints using your web framework. These will be called by your in-browser JavaScript to register and unregister devices.<\/p>\n<p>This article won\u2019t touch on the browser-side code or how it works. You\u2019ll need to put together a service worker that responds to incoming push events and displays a notification to the user.<\/p>\n<p>At a high-level, the Web Push flow looks like this:<\/p>\n<ol type=\"1\">\n<li>A push subscription is registered in the browser. The browser issues a unique endpoint URL to your JavaScript.<\/li>\n<li>Your JavaScript sends the subscription data to your server and identifies the user it applies to.<\/li>\n<li>When your backend needs to send a push notification, create a payload and send it to the endpoint URL reported as part of the subscription data.<\/li>\n<li>The user\u2019s browser will receive the payload via the vendor\u2019s notification delivery platform. Your JavaScript service worker handles the consequent event and uses the browser\u2019s notification API to alert the user.<\/li>\n<\/ol>\n<p>Here\u2019s how to implement the server-side aspects of steps 1 to 3.<\/p>\n<h2 id=\"getting-setup\"><span class=\"ez-toc-section\" id=\"Getting_Setup\"><\/span>Getting Setup<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>We\u2019ll use the <code>web-push<\/code> Packagist package by minishlink. This abstracts the interactions with each browser notification platform so you don\u2019t have to manually distinguish between endpoint types.<\/p>\n<p>Add the package to your project using Composer:<\/p>\n<pre>composer require minishlink\/web-push<\/pre>\n<p>To use the latest version, you need PHP 7.2 or greater with the <code>gmp<\/code>, <code>mbstring<\/code>, <code>curl<\/code>, and <code>openssl<\/code> extensions. If you must use an older PHP release, lock the package <a rel=\"nofollow noopener\" target=\"_blank\" href=\"https:\/\/packagist.org\/packages\/minishlink\/web-push\">to an earlier version<\/a> to maintain compatibility.<\/p>\n<p>The library exposes a core <code>WebPush<\/code> class with methods that let you send notifications individually or as batches. Subscriptions are represented by instances of the <code>Subscription<\/code> class.<\/p>\n<h2 id=\"providing-vapid-keys\"><span class=\"ez-toc-section\" id=\"Providing_VAPID_Keys\"><\/span>Providing VAPID Keys<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>Trust in the standards-compliant Web Push ecosystem is enforced through the use of <a rel=\"nofollow noopener\" target=\"_blank\" href=\"https:\/\/developers.google.com\/web\/fundamentals\/push-notifications\/web-push-protocol\">VAPID keys<\/a>. Your server needs a VAPID key pair so it can authenticate itself to browsers. The public key should be exposed via an API endpoint.<\/p>\n<p>You can generate a VAPID key set using the <code>web-push<\/code> package:<\/p>\n<div class=\"wp-geshi-highlight-wrap5\">\n<div class=\"wp-geshi-highlight-wrap4\">\n<div class=\"wp-geshi-highlight-wrap3\">\n<div class=\"wp-geshi-highlight-wrap2\">\n<div class=\"wp-geshi-highlight-wrap\">\n<div class=\"wp-geshi-highlight\">\n<div class=\"php\">\n<pre class=\"de1\"><span class=\"kw2\">use<\/span> MinishlinkWebPushVAPID<span class=\"sy0\">;<\/span>\n\u00a0\n<span class=\"re0\">$keyset<\/span> <span class=\"sy0\">=<\/span> VAPID<span class=\"sy0\">::<\/span><span class=\"me2\">createVapidKeys<\/span><span class=\"br0\">(<\/span><span class=\"br0\">)<\/span><span class=\"sy0\">;<\/span>\n\u00a0\n<span class=\"co1\">\/\/ public key - this needs to be accessible via an API endpoint<\/span>\n<span class=\"kw1\">echo<\/span> <span class=\"re0\">$keyset<\/span><span class=\"br0\">[<\/span><span class=\"st0\">\"publicKey\"<\/span><span class=\"br0\">]<\/span><span class=\"sy0\">;<\/span>\n\u00a0\n<span class=\"co1\">\/\/ private key - never expose this!<\/span>\n<span class=\"kw1\">echo<\/span> <span class=\"re0\">$keyset<\/span><span class=\"br0\">[<\/span><span class=\"st0\">\"privateKey\"<\/span><span class=\"br0\">]<\/span><span class=\"sy0\">;<\/span>\n\u00a0\n<span class=\"kw3\">file_put_contents<\/span><span class=\"br0\">(<\/span><span class=\"st0\">\"vapid.json\"<\/span><span class=\"sy0\">,<\/span> <span class=\"kw3\">json_encode<\/span><span class=\"br0\">(<\/span><span class=\"re0\">$keyset<\/span><span class=\"br0\">)<\/span><span class=\"br0\">)<\/span><span class=\"sy0\">;<\/span><\/pre>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<p>Generate keys for your system and store them to a persistent location. Add an API endpoint so your client-side JavaScript can retrieve the public key. This will be used to setup the browser\u2019s push subscription. The user\u2019s device will accept incoming push events if they\u2019ve been signed using the corresponding VAPID private key.<\/p>\n<h2 id=\"registering-push-subscriptions\"><span class=\"ez-toc-section\" id=\"Registering_Push_Subscriptions\"><\/span>Registering Push Subscriptions<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>The next step in the sequence is receiving push subscription requests from your clients. Once the browser\u2019s confirmed a new push subscription, your JavaScript should send the subscription\u2019s endpoint URL and associated authentication keys to your server. Store these details alongside the user\u2019s ID so you can retrieve all the push-enrolled devices linked to the user later on.<\/p>\n<p>We\u2019re omitting code samples for this step as the implementation depends on your data storage layer and the values your JavaScript sends up. Typically, this will be a JSON representation of a <a rel=\"nofollow noopener\" target=\"_blank\" href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/API\/PushSubscription\"><code>PushSubscription<\/code><\/a> object. You need a simple set of database-backed CRUD API endpoints to create a subscription, replace an existing one, and request a deletion when the user unsubscribes.<\/p>\n<h2 id=\"preparing-subscriptions\"><span class=\"ez-toc-section\" id=\"Preparing_Subscriptions\"><\/span>Preparing Subscriptions<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>Once a client\u2019s successfully registered you can start sending notifications using the <code>web-push<\/code> library. Begin by creating an instance of the <code>WebPush<\/code> class:<\/p>\n<div class=\"wp-geshi-highlight-wrap5\">\n<div class=\"wp-geshi-highlight-wrap4\">\n<div class=\"wp-geshi-highlight-wrap3\">\n<div class=\"wp-geshi-highlight-wrap2\">\n<div class=\"wp-geshi-highlight-wrap\">\n<div class=\"wp-geshi-highlight\">\n<div class=\"php\">\n<pre class=\"de1\"><span class=\"kw2\">use<\/span> MinishlinkWebPushWebPush<span class=\"sy0\">;<\/span>\n\u00a0\n<span class=\"re0\">$webPush<\/span> <span class=\"sy0\">=<\/span> <span class=\"kw2\">new<\/span> WebPush<span class=\"br0\">(<\/span><span class=\"br0\">[<\/span>\n    <span class=\"st0\">\"VAPID\"<\/span> <span class=\"sy0\">=&gt;<\/span> <span class=\"br0\">[<\/span>\n        <span class=\"st0\">\"subject\"<\/span> <span class=\"sy0\">=&gt;<\/span> <span class=\"st0\">\"https:\/\/example.com\"<\/span><span class=\"sy0\">,<\/span>\n        <span class=\"st0\">\"publicKey\"<\/span> <span class=\"sy0\">=&gt;<\/span> <span class=\"st0\">\"VAPID_Public_Key_Here\"<\/span><span class=\"sy0\">,<\/span>\n        <span class=\"st0\">\"privateKey\"<\/span> <span class=\"sy0\">=&gt;<\/span> <span class=\"st0\">\"VAPID_Private_Key_Here\"<\/span>\n    <span class=\"br0\">]<\/span>\n<span class=\"br0\">]<\/span><span class=\"br0\">)<\/span><span class=\"sy0\">;<\/span><\/pre>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<p>You can reuse one <code>WebPush<\/code> instance each time you send a notification. The library needs to be configured with the VAPID key set you generated earlier. Keys should be encoded as Base64 but this is handled for you if you create them with the library.<\/p>\n<p>The VAPID <code>subject<\/code> is used to identify your server and its contact details. You can supply a website URL or a <code>mailto:<\/code> email address link.<\/p>\n<p>Next you need to retrieve the push subscription you\u2019ll be sending to. Use your data access system to lookup the push endpoint URLs associated with the user you want to send to. Convert each subscription to a <code>Subscription<\/code> instance:<\/p>\n<div class=\"wp-geshi-highlight-wrap5\">\n<div class=\"wp-geshi-highlight-wrap4\">\n<div class=\"wp-geshi-highlight-wrap3\">\n<div class=\"wp-geshi-highlight-wrap2\">\n<div class=\"wp-geshi-highlight-wrap\">\n<div class=\"wp-geshi-highlight\">\n<div class=\"php\">\n<pre class=\"de1\"><span class=\"kw2\">use<\/span> MinishlinkWebPushSubscription<span class=\"sy0\">;<\/span>\n\u00a0\n<span class=\"co1\">\/\/ Get user's push data...<\/span>\n<span class=\"co1\">\/\/ SELECT * FROM push_subscriptions WHERE user_id = 123456<\/span>\n\u00a0\n<span class=\"re0\">$subscription<\/span> <span class=\"sy0\">=<\/span> Subscription<span class=\"sy0\">::<\/span><span class=\"me2\">create<\/span><span class=\"br0\">(<\/span><span class=\"br0\">[<\/span>\n    <span class=\"st0\">\"endpoint\"<\/span> <span class=\"sy0\">=&gt;<\/span> <span class=\"st0\">\"https:\/\/fcm.google.com\/...\"<\/span><span class=\"sy0\">,<\/span>\n    <span class=\"st0\">\"contentEncoding\"<\/span> <span class=\"sy0\">=&gt;<\/span> <span class=\"st0\">\"aesgcm\"<\/span><span class=\"sy0\">,<\/span>\n    <span class=\"st0\">\"authToken\"<\/span> <span class=\"sy0\">=&gt;<\/span> <span class=\"st0\">\"&lt;auth token from JavaScript PushSubscription object&gt;\"<\/span>\n    <span class=\"st0\">\"keys\"<\/span> <span class=\"sy0\">=&gt;<\/span> <span class=\"br0\">[<\/span>\n        <span class=\"st0\">\"auth\"<\/span> <span class=\"sy0\">=&gt;<\/span> <span class=\"st0\">\"&lt;auth token from JavaScript PushSubscription object&gt;\"<\/span><span class=\"sy0\">,<\/span>\n        <span class=\"st0\">\"p256dh\"<\/span> <span class=\"sy0\">=&gt;<\/span> <span class=\"st0\">\"&lt;p256dh token from JavaScript PushSubscription object&gt;\"<\/span>\n    <span class=\"br0\">]<\/span>\n<span class=\"br0\">]<\/span><span class=\"br0\">)<\/span><span class=\"sy0\">;<\/span><\/pre>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<p>The <code>auth<\/code> property of the <a rel=\"nofollow noopener\" target=\"_blank\" href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/API\/PushSubscription\"><code>PushSubscription<\/code><\/a> is repeated twice to cope with two different versions of the spec used by browser services. The P256DH property is another public key which should be supplied when set on the subscription.<\/p>\n<p>The <code>web-push<\/code> library is compatible with Chrome and Firefox push endpoints. It\u2019ll also work with any other Web Push implementation that meets the current standard.<\/p>\n<h2 id=\"sending-a-notification\"><span class=\"ez-toc-section\" id=\"Sending_a_Notification\"><\/span>Sending a Notification<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>Now combine your <code>WebPush<\/code> and <code>Subscription<\/code> instances to send a notification:<\/p>\n<div class=\"wp-geshi-highlight-wrap5\">\n<div class=\"wp-geshi-highlight-wrap4\">\n<div class=\"wp-geshi-highlight-wrap3\">\n<div class=\"wp-geshi-highlight-wrap2\">\n<div class=\"wp-geshi-highlight-wrap\">\n<div class=\"wp-geshi-highlight\">\n<div class=\"php\">\n<pre class=\"de1\"><span class=\"re0\">$result<\/span> <span class=\"sy0\">=<\/span> <span class=\"re0\">$webPush<\/span> <span class=\"sy0\">-&gt;<\/span> <span class=\"me1\">sendOneNotification<\/span><span class=\"br0\">(<\/span>\n    <span class=\"re0\">$subscription<\/span><span class=\"sy0\">,<\/span>\n    <span class=\"kw3\">json_encode<\/span><span class=\"br0\">(<\/span><span class=\"br0\">[<\/span>\n        <span class=\"st0\">\"message\"<\/span> <span class=\"sy0\">=&gt;<\/span> <span class=\"st0\">\"Demo notification\"<\/span><span class=\"sy0\">,<\/span>\n        <span class=\"st0\">\"foo\"<\/span> <span class=\"sy0\">=&gt;<\/span> <span class=\"st0\">\"bar\"<\/span>\n    <span class=\"br0\">]<\/span><span class=\"br0\">)<\/span>\n<span class=\"br0\">)<\/span><span class=\"sy0\">;<\/span><\/pre>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<p>Calling <code>sendOneNotification()<\/code> provides im<a href=\"https:\/\/buradabiliyorum.com\/en\/category\/social-mediaa\/\" data-internallinksmanager029f6b8e52c=\"1\" title=\"Social Media\" target=\"_blank\" rel=\"noopener\">media<\/a>te delivery for a single notification. The payload in this case is a JSON-encoded array with two properties. It\u2019s up to you what data you send and the format you use \u2013 your JavaScript client receives it as-is and can interpret it as necessary.<\/p>\n<p>Sending a notification returns a result class that lets you check whether the operation succeeded:<\/p>\n<div class=\"wp-geshi-highlight-wrap5\">\n<div class=\"wp-geshi-highlight-wrap4\">\n<div class=\"wp-geshi-highlight-wrap3\">\n<div class=\"wp-geshi-highlight-wrap2\">\n<div class=\"wp-geshi-highlight-wrap\">\n<div class=\"wp-geshi-highlight\">\n<div class=\"php\">\n<pre class=\"de1\"><span class=\"kw1\">if<\/span> <span class=\"br0\">(<\/span><span class=\"re0\">$result<\/span> <span class=\"sy0\">-&gt;<\/span> <span class=\"me1\">isSuccess<\/span><span class=\"br0\">(<\/span><span class=\"br0\">)<\/span><span class=\"br0\">)<\/span> <span class=\"br0\">{<\/span>\n    <span class=\"co1\">\/\/ all good<\/span>\n<span class=\"br0\">}<\/span>\n<span class=\"kw1\">else<\/span> <span class=\"br0\">{<\/span>\n\u00a0\n    <span class=\"co1\">\/\/ something went wrong<\/span>\n    <span class=\"kw3\">error_log<\/span><span class=\"br0\">(<\/span><span class=\"re0\">$result<\/span> <span class=\"sy0\">-&gt;<\/span> <span class=\"me1\">getReason<\/span><span class=\"br0\">(<\/span><span class=\"br0\">)<\/span><span class=\"br0\">)<\/span><span class=\"sy0\">;<\/span>\n\u00a0\n    <span class=\"co1\">\/\/ provides raw HTTP response data<\/span>\n    <span class=\"kw3\">error_log<\/span><span class=\"br0\">(<\/span><span class=\"re0\">$result<\/span> <span class=\"sy0\">-&gt;<\/span> <span class=\"me1\">getResponse<\/span><span class=\"br0\">(<\/span><span class=\"br0\">)<\/span><span class=\"br0\">)<\/span><span class=\"sy0\">;<\/span>\n\u00a0\n<span class=\"br0\">}<\/span><\/pre>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<p>You can take action to retry or cancel the delivery if an error occurs.<\/p>\n<p>Notification subscriptions can also expire. Call the <code>isSubscriptionExpired()<\/code> method on a result class to determine whether this is the reason for the failure. You could delete the subscription from your database in this scenario, ensuring you don\u2019t send anything else to a dead endpoint.<\/p>\n<h2 id=\"batching-notifications\"><span class=\"ez-toc-section\" id=\"Batching_Notifications\"><\/span>Batching Notifications<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>Notifications can be batched together for delivery with one method call:<\/p>\n<div class=\"wp-geshi-highlight-wrap5\">\n<div class=\"wp-geshi-highlight-wrap4\">\n<div class=\"wp-geshi-highlight-wrap3\">\n<div class=\"wp-geshi-highlight-wrap2\">\n<div class=\"wp-geshi-highlight-wrap\">\n<div class=\"wp-geshi-highlight\">\n<div class=\"php\">\n<pre class=\"de1\"><span class=\"re0\">$webPush<\/span> <span class=\"sy0\">-&gt;<\/span> <span class=\"me1\">queueNotification<\/span><span class=\"br0\">(<\/span><span class=\"re0\">$subscription<\/span><span class=\"sy0\">,<\/span> <span class=\"br0\">[<\/span><span class=\"st0\">\"msg\"<\/span> <span class=\"sy0\">=&gt;<\/span> <span class=\"st0\">\"first\"<\/span><span class=\"br0\">]<\/span><span class=\"br0\">)<\/span><span class=\"sy0\">;<\/span>\n<span class=\"re0\">$webPush<\/span> <span class=\"sy0\">-&gt;<\/span> <span class=\"me1\">queueNotification<\/span><span class=\"br0\">(<\/span><span class=\"re0\">$subscription<\/span><span class=\"sy0\">,<\/span> <span class=\"br0\">[<\/span><span class=\"st0\">\"msg\"<\/span> <span class=\"sy0\">=&gt;<\/span> <span class=\"st0\">\"second\"<\/span><span class=\"br0\">]<\/span><span class=\"br0\">)<\/span><span class=\"sy0\">;<\/span>\n\u00a0\n<span class=\"kw1\">foreach<\/span> <span class=\"br0\">(<\/span><span class=\"re0\">$webPush<\/span> <span class=\"sy0\">-&gt;<\/span> <span class=\"kw3\">flush<\/span><span class=\"br0\">(<\/span><span class=\"br0\">)<\/span> <span class=\"kw1\">as<\/span> <span class=\"re0\">$i<\/span> <span class=\"sy0\">=&gt;<\/span> <span class=\"re0\">$result<\/span><span class=\"br0\">)<\/span> <span class=\"br0\">{<\/span>\n    <span class=\"kw1\">echo<\/span> <span class=\"br0\">(<\/span><span class=\"st0\">\"Notification <span class=\"es4\">$i<\/span> was \"<\/span> <span class=\"sy0\">.<\/span> <span class=\"br0\">(<\/span><span class=\"re0\">$result<\/span> <span class=\"sy0\">-&gt;<\/span> <span class=\"me1\">isSuccess<\/span><span class=\"br0\">(<\/span><span class=\"br0\">)<\/span> ? <span class=\"st0\">\"sent\"<\/span> <span class=\"sy0\">:<\/span> <span class=\"st0\">\"not sent\"<\/span><span class=\"br0\">)<\/span><span class=\"br0\">)<\/span><span class=\"sy0\">;<\/span>\n<span class=\"br0\">}<\/span><\/pre>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<p>This is useful when you know you\u2019ll be sending a large number of notifications in a short timeframe. Queue all your payloads and let <code>web-push<\/code> deliver them in the optimal way.<\/p>\n<p>You can limit the number of notifications sent in a single <code>flush()<\/code> by passing an integer to the method:<\/p>\n<div class=\"wp-geshi-highlight-wrap5\">\n<div class=\"wp-geshi-highlight-wrap4\">\n<div class=\"wp-geshi-highlight-wrap3\">\n<div class=\"wp-geshi-highlight-wrap2\">\n<div class=\"wp-geshi-highlight-wrap\">\n<div class=\"wp-geshi-highlight\">\n<div class=\"php\">\n<pre class=\"de1\"><span class=\"re0\">$webPush<\/span> <span class=\"sy0\">-&gt;<\/span> <span class=\"kw3\">flush<\/span><span class=\"br0\">(<\/span><span class=\"nu0\">100<\/span><span class=\"br0\">)<\/span><span class=\"sy0\">;<\/span>     <span class=\"co1\">\/\/ send 100 messages<\/span><\/pre>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<p>The default value is <code>1000<\/code>.<\/p>\n<h2 id=\"notification-options\"><span class=\"ez-toc-section\" id=\"Notification_Options\"><\/span>Notification Options<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p><code>sendOneNotification()<\/code> and <code>queueNotification()<\/code> accept the following options as a third array argument:<\/p>\n<ul>\n<li><strong><code>TTL<\/code><\/strong> \u2013 Controls how long the browser\u2019s notification platform will hold onto the notification if it can\u2019t be passed to the user\u2019s device immediately. If the user\u2019s device is offline, platforms default to trying to deliver it for the next four weeks. If you\u2019re sending a notification that won\u2019t be relevant next week, adjust the TTL accordingly so the user doesn\u2019t see outdated content.<\/li>\n<li><strong><code>urgency<\/code><\/strong> \u2013 Accepts <code>normal<\/code>, <code>low<\/code> or <code>very-low<\/code> as values. Some platforms may use this to adjust the frequency of notification delivery. Devices that enter a battery saving mode may suspend delivery of non-urgent notifications.<\/li>\n<li><strong><code>batchSize<\/code><\/strong> \u2013 This has the same effect as the argument to <code>flush()<\/code> described above.<\/li>\n<\/ul>\n<p>You can configure default option values using the second argument to the <code>WebPush<\/code> constructor:<\/p>\n<div class=\"wp-geshi-highlight-wrap5\">\n<div class=\"wp-geshi-highlight-wrap4\">\n<div class=\"wp-geshi-highlight-wrap3\">\n<div class=\"wp-geshi-highlight-wrap2\">\n<div class=\"wp-geshi-highlight-wrap\">\n<div class=\"wp-geshi-highlight\">\n<div class=\"php\">\n<pre class=\"de1\"><span class=\"re0\">$webPush<\/span> <span class=\"sy0\">=<\/span> <span class=\"kw2\">new<\/span> WebPush<span class=\"br0\">(<\/span><span class=\"br0\">[<\/span><span class=\"st0\">\"VAPID\"<\/span> <span class=\"sy0\">=&gt;<\/span> <span class=\"br0\">[<\/span><span class=\"sy0\">...<\/span><span class=\"br0\">]<\/span><span class=\"br0\">]<\/span><span class=\"sy0\">,<\/span> <span class=\"br0\">[<\/span><span class=\"st0\">\"TTL\"<\/span> <span class=\"sy0\">=&gt;<\/span> <span class=\"nu0\">3600<\/span><span class=\"br0\">]<\/span><span class=\"br0\">)<\/span><span class=\"sy0\">;<\/span><\/pre>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<h2 id=\"summary\"><span class=\"ez-toc-section\" id=\"Summary\"><\/span>Summary<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>The <code>web-push<\/code> library makes it easy to send Web Push notifications using PHP. You get an abstraction layer atop the various browser platforms that supports batching, error handling, and all Web Push features.<\/p>\n<p>The Web Push mechanism is an unusual browser system as it\u2019s reliant on remote server-side components you supply yourself. This can make it seem opaque and technical. In practice, creating a simple PHP backend is quick and easy; the frontend implementation is usually the more time-consuming aspect, particularly if you\u2019re not already using service worker features.\n<\/p><\/div>\n<blockquote><p><strong><span style=\"color: #ff6600;\">If you liked the article, do not forget to share it with your friends. Follow us on\u00a0<span style=\"color: #ff0000;\"><a style=\"color: #ff0000;\" href=\"https:\/\/news.google.com\/publications\/CAAqBwgKMLG0nwswvr63Aw\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">Google News<\/a><\/span>\u00a0too, click on the star and choose us from your favorites.<\/span><\/strong><\/p><\/blockquote>\n<blockquote>\n<p style=\"text-align: center;\">For forums sites go to <span style=\"color: #ff9900;\"><a style=\"color: #ff9900;\" href=\"https:\/\/forum.buradabiliyorum.com\/\" target=\"_blank\" rel=\"noopener\">Forum.BuradaBiliyorum.Com<\/a><\/span><\/strong><\/p>\n<\/blockquote>\n<blockquote>\n<p style=\"text-align: center;\"><strong>If you want to read more like this article, you can visit our <span style=\"color: #ff9900;\"><a style=\"color: #ff9900;\" href=\"https:\/\/en.buradabiliyorum.com\/technology\/\" target=\"_blank\" rel=\"noopener\">Technology category.<\/a><\/span><\/strong><\/p>\n<\/blockquote>\n<p><span style=\"color: black;\"><a style=\"color: #ff9900;\" href=\"https:\/\/www.cloudsavvyit.com\/13932\/how-to-send-web-push-notifications-with-php\/\" target=\"_blank\" rel=\"noopener\">Source<\/a><\/span><\/p>\n","protected":false},"excerpt":{"rendered":"<p>&#8220;#How to Send Web Push Notifications With PHP \u2013 CloudSavvy IT&#8221; The Web Push API lets you send push notifications to web browsers and APIs. While most of the logic happens in the browser, you still need a server-side component to generate your notifications. Here\u2019s how to implement a Web Push backend using PHP. Prerequisites&#8230;<\/p>\n","protected":false},"author":1,"featured_media":329113,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"fifu_image_url":"https:\/\/www.cloudsavvyit.com\/p\/uploads\/2017\/08\/1ac500da.png","fifu_image_alt":"","footnotes":""},"categories":[18],"tags":[],"class_list":["post-329112","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-technology"],"_links":{"self":[{"href":"https:\/\/buradabiliyorum.com\/en\/wp-json\/wp\/v2\/posts\/329112","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/buradabiliyorum.com\/en\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/buradabiliyorum.com\/en\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/buradabiliyorum.com\/en\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/buradabiliyorum.com\/en\/wp-json\/wp\/v2\/comments?post=329112"}],"version-history":[{"count":0,"href":"https:\/\/buradabiliyorum.com\/en\/wp-json\/wp\/v2\/posts\/329112\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/buradabiliyorum.com\/en\/wp-json\/wp\/v2\/media\/329113"}],"wp:attachment":[{"href":"https:\/\/buradabiliyorum.com\/en\/wp-json\/wp\/v2\/media?parent=329112"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/buradabiliyorum.com\/en\/wp-json\/wp\/v2\/categories?post=329112"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/buradabiliyorum.com\/en\/wp-json\/wp\/v2\/tags?post=329112"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}