如果你关注 Typecho 的更新日志,会发现我今天增加了一个比较重要的新特性:异步回调
https://github.com/typecho/typecho/commit/f180e8452de92a99d189779a67b6caf1ce2b26cf
顾名思义,它允许你创建一个异步的方法,并接受回调。主要用于一些会长时间阻塞同步请求而又不必等待返回结果的操作。
它的主要原理是:
将这些等待时间较长的操作,注册到另一个 URL 中,当需要执行它们的时候,主进程带上必要的参数请求这个URL。同时不必等待这个请求返回,立即断开这个连接。此时,在执行 URL 的那个进程上,调用 PHP 的 ignore_user_abort
函数,忽略请求端的主动断开,继续执行到所有代码结束。
举一个典型的使用场景:评论的邮件提醒功能。发邮件由于需要用 SOCKS 请求 SMTP 接口,从发起连接,完成认证到发送结束,往往需要很长时间。这个时候用户的评论发送请求就会一直阻塞在那里,体验会非常不好。如果用异步回调将邮件发送过程封装进去,用户在提交评论后就不必等待邮件发送结束了。
使用方法,首先在 active
的时候注册一个回调放到 Widget_Service
里去
public static function activate() {
Typecho_Plugin::factory('Widget_Feedback')->finishComment = array('Mailer_Plugin', 'send');
Typecho_Plugin::factory('Widget_Service')->sendMail = array('Mailer_Plugin', 'sendMail');
}
在上面的代码中,我们还注册了一个 send
方法到 Widget_Feedback
的 finishComment
钩子点,用于将参数发送到异步的回调中,这个 send
函数的实现非常简单,它不包含任何实际的发送代码,只是用 Helper::requestService
把刚刚新增的那条评论 coid
发送到异步回调 sendMail
中。
public static function send($comment)
{
Helper::requestService('sendMail', $comment->coid);
}
而另一个用于在异步回调中执行的函数就包含了完整的发送逻辑
public static function sendMail($commentId)
{
$options = Helper::options();
$pluginOptions = $options->plugin('Mailer');
$comment = Helper::widgetById('comments', $commentId);
if (empty($pluginOptions->host)) {
return;
}
if (!$comment->have() || empty($comment->mail)) {
return;
}
$mail = new PHPMailer(false);
// ... 剩下的都是请求代码
}
另外,我们还新增了一个常量 __TYPECHO_SERVICE_URL__
,用于提高回调的性能。因为这个回调本质是通过 HTTP 网络接口请求自己,默认会使用你的外网正式访问地址作为访问前缀,对于某些使用了反向代理的用户其实可以更快地响应。首先在 /etc/hosts
文件里把网站域名指向 127.0.0.1
,这样在发起网络请求的时候就不必使用外部的 DNS 解析,而且网络请求也会走本地环路大大地节省时间,如果你在本地使用了一个反向代理,可以在 config.inc.php
中直接把 __TYPECHO_SERVICE_URL__
设置成反向代理的访问地址,比如
define('__TYPECHO_SERVICE_URL__', 'http://127.0.0.1:8080');
这是我做的一个完整的例子,异步回调版的评论邮件插件 Mailer.zip 。
注意:这个插件只能在最新的开发版中使用。
这个好,邮件提醒终于有一个个完美的插件了。
启用插件后 syntax error, unexpected '000644' (T_LNUMBER)
ParseError: syntax error, unexpected '000644' (T_LNUMBER) in /home/locred/public_html/usr/plugins/mailer.php:4876
0 /home/locred/public_html/var/Widget/Plugins/Edit.php(308): Widget_Plugins_Edit->activate('mailer')1 /home/locred/public_html/var/Widget/Do.php(82): Widget_Plugins_Edit->action()2 /home/locred/public_html/var/Typecho/Widget.php(221): Widget_Do->execute()3 /home/locred/public_html/var/Typecho/Router.php(135): Typecho_Widget::widget('Widget_Do', NULL, Array)4 /home/locred/public_html/index.php(23): Typecho_Router::dispatch()5 {main}Stack trace:
你的插件目录放错了吧,这些文件要放到 usr/plugins/Mailer 目录下,你是不是把里面的文件解压出来了
这个我下载下来是一窜数字 我把里面的文件重命名mailer.php的
大佬 这个文件由zip包吗..
已经可以了 谢谢
博主博主 最新开发版12.13
博主博主 最新开发版12.13点开发版启用后错误500怎么办 官方找不到11.15的开发版了 能分享个嘛.
我并没有重现这个错误,你在 config.inc.php 里加上一行
define('__TYPECHO_DEBUG__', true);
看看具体的报错信息
添加了,,还是显示不了 额额 就直接错误500。
修改 插件名称 Typecho-Plugin-Mailer-master 改 Mailer
希望正式版能有这个功能
已升级te最新开发版,已实装此插件,效果拔群,虽说设置的时候有错误提示吧,但也不耽误用,正常发信。
为了这个等会就升级开发版
测试了下 评论后邮件不会发送是什么原因呢
你的邮件参数是正确的么
是正确的 保存的时候没有提示出错,而且用这个配置使用另外一个插件是正常的
我用的是正常的,你看看日志,有没有正常回调
失败了,找不到日志,请问是不是需要修改代码才可以使用?
搞定了 不能用自己的SMTP地址而要用smtp.mxhichina.com。。。而且保存会提示向服务器发送指令错误,但是实际已经可以用了
这个压缩包里面是啥啊,未知属性 不会用!
好功能,希望评论邮件提醒插件能够尽快移植到正式版中。其实插件不用多,几个必要且使用的就行,尤其是官方版插件安全放心踏实。
(Mailer插件)在后台回复的内容好像没有邮件提醒。
我用的是QQ企业免费邮箱,SSL/465端口,也是提示向服务器发送指令错误,但是能用。
其实我是真没有看懂异步回调,我就是喜欢分享的这个邮件插件!用起来感觉超好!速度快又稳定,强烈建议博主持续更新和优化这个插件, Typecho 确实需要一个轻便好用的评论邮件提醒插件的!
升级为最新版的开发版,然后使用插件,却发现邮件没有发送,在Plugin.php中修改了下代码:
file_put_contents(__DIR__ . '/mailer.txt', 'begin'.PHP_EOL, FILE_APPEND);
Helper::requestService('sendMail', $comment->coid);
file_put_contents(__DIR__ . '/mailer.txt', 'end'.PHP_EOL, FILE_APPEND);
以及:
public static function sendMail($commentId)
{
评论后,可以看到begin和end的记录,可没有sendMail的记录,请问下是什么原因呢?
说明没有更新到typecho开发版本
邮件服务器连接失败
dalao有个问题想问一下 我大概17年9月份安得这个插件(确保一下这个插件后面有没有更新) 发现了一个问题 邮件评论的时候会把其他人的邮箱暴露出去(插件用了邮件群发,群发的那些人的邮箱收件人都能看见)。如果能修复一下就好了
+1 自己还是改不来
不支持 sqlite 数据库,建议更新支持下。一个个人博客,很少去用mysql。
[...]好在在joyqi.com的【关于新增的异步回调方法】一文里,作者分享的支持异步回调版的评论邮件插件 Mailer 明月竟然可以使用,插件非常的简洁,性能表现很不错,所以明月就推荐给大家,有需要的可以使用体验一下。[...]
又学习长知识了。