介绍
在构建PHP长期运行脚本时,有时希望在脚本运行完成后通知用户。这可能是因为脚本成功完成,或者是因为有错误发生。
在我的一些Laravel项目中创建了一些长期运行的Artisan命令之后,我多次想到要做这件事。
实现这一目标的一个非常好的(并且非常酷!)方法是使用桌面通知。
在这篇文章中,我们将探讨如何使用 "JoliNotif"(jolicode/jolinotif
)包在PHP CLI应用程序中显示桌面通知。我主要是一个Laravel开发者,所以示例将以从Laravel Artisan命令中触发通知为基础,但应该很容易将这些概念应用到我们的PHP CLI应用程序中。
JoliNotif是什么?
JoliNotif 是一个跨平台包,允许您在Windows、macOS和Linux上运行的应用程序中显示桌面通知。
该工具由JoliCode开发和维护。在撰写本文时,它已经在GitHub上超过520万次下载,并获得1.3k个星标。
这是一个优秀的包,且使用起来非常简单!
几年前,我出于一个概念验证的目的,构建了一个小的Laravel包,名为”Laravel Executor“。这是一个允许您使用PHP编写脚本的包,然后可以从Artisan命令中执行它们的包。它背后的理念是您可以用它来构建部署脚本或其他实用工具。这个包主要是为了练习我的Web开发技能,并了解更多有关构建Laravel包的知识而建立的,可在这里阅读我从构建自己的Laravel包中学到的5个教训。
我在Laravel Executor中使用了JoliNotif,这样开发者就可以给他们的Artisan命令添加通知。我认为这是一个非常酷的小功能,为这个包添加了一些额外的光泽。
如果您正在构建一个包、CLI应用或Laravel Artisan命令,你可能还希望给它添加桌面通知。
那么,让我们深入研究并看看如何使用它吧!
安装包
为了开始使用jolicode/jolinotif
,我们需要使用Composer将其安装到我们的项目中。我们可以在项目根目录中运行以下命令:
composer require jolicode/jolinotif
现在,该包应该已经安装就绪,可以使用了!
创建基本通知
为了创建通知,我们首先需要创建一个新的Joli\JoliNotif\Notification
类实例。这个对象包含了你想要向用户显示的通知数据。
创建了新的实例后,我们将将它传递给一个“Notifier”,该Notifier负责将通知显示给用户。我们将在本文的稍后部分更详细地介绍Notifier。您可以使用NotifierFactory::create()
方法访问Notifier。
要发送一个基本的通知,我们可以这样做:
use Joli\JoliNotif\Notification;
use Joli\JoliNotif\NotifierFactory;
$notification = (new Notification())
->setBody('The long script has finished!')
->setTitle('My Awesome PHP CLI App!');
NotifierFactory::create()->send($notification);
运行上面提到的代码会产生一个桌面通知,显示给用户,大致如下所示。
值得注意的是,通知的主体(使用setBody
方法设置)是一个必需字段。如果您不设置它,则在尝试显示通知时将引发异常。
为了说明您如何在一个Laravel Artisan命令中使用这个功能,让我们看一个快速例子。假设我们构建了一个长时间运行的Artisan命令,它执行一些处理,并且我们希望在完成后通知用户。我们的命令可能如下所示:
declare(strict_types=1);
namespace App\Console\Commands;
use Illuminate\Console\Command;
use Joli\JoliNotif\Notification;
use Joli\JoliNotif\NotifierFactory;
final class DesktopNotification extends Command
{
protected $signature = 'app:desktop-notification';
protected $description = 'Run a long script';
public function handle(): int
{
// Run the long script here...
$this->sendDesktopNotification();
return self::SUCCESS;
}
private function sendDesktopNotification(): void
{
$notification = (new Notification())
->setBody('The long script has finished!')
->setTitle('My Awesome PHP CLI App!');
NotifierFactory::create()->send($notification);
}
}
自定义通知
根据所使用的Notifier,您可以使用多种方式来自定义通知。
更改副标题
一些Notifier允许您向通知添加副标题。这是一段小文本,显示在通知标题下方。要添加副标题到通知,您可以使用通知对象上的addOption
方法,示例如下:
$notification = (new Notification())
->setBody('The long script has finished!')
->setTitle('My Awesome PHP CLI App!')
->addOption('subtitle', 'This is a subtitle');
NotifierFactory::create()->send($notification);
在macOS机器上运行上述代码会得到类似这样的通知。
需要注意的是,如果Notifier不支持副标题,它将被忽略,并不会显示给用户。
更改声音
根据所使用的Notifier,您还可以更改通知显示给用户时播放的声音。要做到这一点,您可以使用通知对象上的addOption
方法,示例如下:
$notification = (new Notification())
->setBody('The long script has finished!')
->setTitle('My Awesome PHP CLI App!')
->addOption('sound', 'Funk');
NotifierFactory::create()->send($notification);
The GitHub仓库列出了在macOS机器上可用的以下声音:Basso, Frog, Hero, Pop, Submarine, Blow, Funk, Morse, Purr, Tink, Bottle, Glass, Ping, Sosumi。
然而,这是一个非详尽列表,因此你可能需要进行一些调查以确定你打算让应用程序运行的操作系统上可用的声音。
更改图标
一些(但不太多)可用的通知器允许你更改通知的图标。如果它们将在其他用户的机器上运行,这将有助于为你的通知增添一些额外的品牌。
要更改通知的图标,你可以像这样在通知对象上使用 setIcon
方法
$notification = (new Notification())
->setBody('The long script has finished!')
->setTitle('My Awesome PHP CLI App!')
->setIcon('/absolute/path/to/my/icon.png');
NotifierFactory::create()->send($notification);
正如我们上面的代码示例中可以看到的那样,我们已经将图标的绝对路径传递给 setIcon
方法。
如果你尝试设置一个图标,而机器的通知器不支持它,那么它将被忽略,且不会显示给用户。
通知器
正如我们简要提到的,JoliNotif 使用“通知器”的概念来在用户的桌面上显示通知。这些是可以在设备上使用的底层通知系统,用于触发桌面通知。默认情况下,它将尝试根据应用程序运行的操作系统来解析一个通知器。
正如我们上面提到的自定义选项,由于通知器之间存在细微差异,这意味着某些功能可能会在某个操作系统上可用,而在其他操作系统上则不可用。
如果一个通知器找不到可以使用的,且操作系统支持它,那么不会抛出任何错误。相反,通知将被忽略且不会被显示给用户。根据通知的使用上下文,这可能不是一个问题。
可用的通知器
在撰写本文时,JoliNotif 支持以下通知器
-
Linux
- KDialogNotifier - 支持:内容,标题
- NotifySendNotifier - 支持:内容,标题,图标
-
macOS
- GrowlNotifyNotifier - 支持:内容,标题,图标
- TerminalNotifierNotifier - 支持:内容,标题
- AppleScriptNotifier - 支持:内容,标题
-
Windows
- SnoreToastNotifier - 支持:内容,标题,图标
- ToasterNotifier - 支持:内容,标题,图标
- NotifuNotifier - 支持:内容,标题,图标
手动指定通知器
可能有些时候你想要手动指定一个(或多个)通知器来尝试使用。这可能是由于你想要使用仅在特定通知器上可用的某些功能。
为此,你可以在 NotifierFactory::create()
方法的第一个参数中传递你期望的通知器到一个数组中。例如,如果你想使用 TerminalNotifier
,你可以这样做
NotifierFactory::create([new TerminalNotifierNotifier()])->send($notification);
在这种情况下,JoliNotif 将尝试使用 TerminalNotifier
通知器来显示通知。如果找不到它,或者操作系统不支持它,则通知将被忽略。否则,它将被显示给用户。
创建你自己的通知器
你可能会想为 JoliNotif 创建自己的通知器。例如,你可能会想要使用当前软件包不支持的通知器。虽然这不是我必须做的事情,但了解这是可能的总是好的。
为了创建你自己的通知器,你需要创建一个实现软件包的 Joli\JoliNotif\Notifier
接口的类。如果你不确定接口是什么,你可能想要阅读我的 "使用接口编写更好的 PHP 代码" 文章。接口看起来像这样
namespace Joli\JoliNotif;
interface Notifier
{
public const PRIORITY_LOW = 0;
public const PRIORITY_MEDIUM = 50;
public const PRIORITY_HIGH = 100;
/**
* This method is called to check whether the notifier can be used on the
* current system or not.
*/
public function isSupported(): bool;
/**
* The supported notifier with the higher priority will be preferred.
*/
public function getPriority(): int;
/**
* Send the given notification.
*
* @throws Exception\InvalidNotificationException if the notification is invalid
*/
public function send(Notification $notification): bool;
}
因此,你的类可能看起来像这样
namespace App\Notifiers;
use Joli\JoliNotif\Notification;
use Joli\JoliNotif\Notifier;
final class MyCustomNotifier implements Notifier
{
public function isSupported(): bool
{
// Check if the notifier is supported on the current system...
}
public function getPriority(): int
{
// Return the priority of the notifier...
}
public function send(Notification $notification): bool
{
// Send the notification...
}
}
一旦您已配置好新的通知器,就可以将其传递给如前所述的NotifierFactory::create()
方法
NotifierFactory::create([new MyCustomNotifier()])->send($notification);
如果您的MyCustomNotifier
类被当前系统支持,则您的通知器的send
方法将被调用,并将通知显示给用户。
其他类型的通知
在本篇文章中,我们介绍了如何在PHP CLI应用程序中显示桌面通知。但可能有时候,您希望以其他方式通知用户,例如发送短信、电子邮件、通过WebSockets进行广播,甚至是WhatsApp消息。
当然,使用这些类型的通知与使用桌面通知的使用场景略有不同。但如果您想了解有关这些类型通知的更多信息,您可能想查看我的一些其他文章
👉 使用Vonage(此前为Nexmo)在Laravel中发送短信
👉 使用Vonage本机SDK在Laravel中发送WhatsApp消息
结论
希望本文让您快速了解如何使用jolicode/jolinotif
包在PHP CLI应用程序和Laravel Artisan命令中显示桌面通知。
如果您喜欢阅读这篇文章,我很乐意听到您的想法。同样,如果您有任何改进未来文章的建议,我也愿意听取。
您可能还感兴趣查看我的220多页电子书(英文)"Battle Ready Laravel",其中更深入地涵盖了类似主题。
或者,您可能想查看我的其他440多页电子书(英文)"Consuming APIs in Laravel",该书籍教授您如何使用Laravel从其他服务消费API。
继续构建精彩的东西!🚀
driesvints, ash-jc-allen, mho liked this article