标签归档:PHP

【翻译】Monolog使用说明 – 即Monolog中文文档

前言

最近项目中使用的Monolog出了点小问题,去翻其文档,发现居然只有英文的。趁业余时间,翻译一下吧。以下是其使用说明中文翻译。更多翻译内容见clarence-pan/monolog-zh-doc.

使用 Monolo

安装

Monolog 在 Packagist monolog/monolog) 上可用,并且可以通过Composer安装:
composer require monolog/monolog
如果你不使用 Composer, 那你可以从 GitHub 上获取代码,然后使用任何兼容 PSR-0 的自动加载器(比如Symfony2 ClassLoader 组件)来加载 Monolog 的类

核心概念

每一个日志服务实例 Logger) 都有一个通道(名称),并有一个处理器 (Handler)栈. 无论何时你添加一条记录到对应的日志服务实例,这个处理器栈将被遍历一遍:每个处理器都将依次决定是否要处理这条记录,而如果要处理,则遍历结束(译注:类似DOM事件冒泡)。这样子可以创建非常灵活的日志配置。比如一个StreamHandler可以把所有日志都写入磁盘,而上面加个MailHandler可以把错误日志作为邮件发送出去。处理器还有一个$bubble属性定义了是否屏蔽某条记录或者处理了某条记录。在这个示例中,配置MailHandler$bubble参数为false则意味着MailHandler将不会把自己已处理过的记录继续冒泡给StreamHandler.你可以创建许多日志服务实例(Logger),每一个则定义一个通道(比如数据库、请求、路由...)。而每一个日志服务实例都可以组合各种各样的处理器,可以共享处理器也可以不共享。这个通道将会在日志中反映出来,从而允许你可以很容易地查看或者筛选记录。每一个处理还会有一个格式化器(Formatter)。如果你没有配置一个,则一个有意义的默认的格式化器将被创建。格式化器用来规范化并格式化输入的记录,以便处理器能输出一些有用的信息。不支持自定义的严重性级别。只支持使用RFC 5424中定义的八个级别(调试/Debug、信息/Info、提示/Notice、警告/Warning、错误/Error、严重/Critical、警报/Alert、紧急/Emergency)来作为基本的筛选目的。不过,如果为了排序或者其他需要灵活性的使用场景,你可以添加加工程序(Processor)从而可以在(处理器)处理前添加额外的信息(标签、用户IP...)。

日志级别

Monolog 支持一下RFC 5424中的日志级别:
  • 调试/DEBU...
阅读全文

一个关于systemd私有目录的奇怪问题

今天遇到一个奇怪的问题 -- PHP里面访问不了/tmp/xhprof-data目录,可是这个目录明明是存在的!今天要使用xhprof进行性能分析,但是打开性能分析开关然后访问页面后却发现没有任何性能数据,很奇怪。检查了下httpd的日志,发现有个fatal error:PHP Fatal error: Uncaught exception 'ErrorException' with message 'fopen(/tmp/xhprof-data/57ad36118dcf0.default.xhprof): failed to open stream: No such file or directory'而对应的PHP代码是类似这样:$file = fopen($filePath, 'w');一般来说这个错误应该是目录不存在或权限不足导致的。那么就检查下对应的目录:
➜  /tmp$ ll -d xhprof-datadrwxrwxrwx. 2 apache apache 41 Aug 12 10:34 xhprof-data
目录是存在的呀,而且为了让PHP能访问,特意设置了全部可以读写,并且所属的用户和组都是apache。然后在代码里面测试下这个目录是否可以访问:
// 简单粗暴点,直接加一行打印看看var_dump(is_dir(dirname($filePath)));die;
结果令人吃惊 -- 居然打印出来是false。难道路径错了吗?把路径也重新打印出来核对下:
// 简单粗暴点,直接加一行打印看看var_dump(dirname($filePath));die;
路径打印出来就是/tmp/xhprof-data,没有错!奇葩问题呀!最后尝试删除掉这个目录,然后在PHP里面加一行自动创建目录:
is_dir(dirname($filePath)) or mkdir(dirname($filePath), 0777, true);
结果,居然通了!到tmp目录下看看跟之前创建的有啥区别:
➜  /tmp$ ll xhprof-datals: cannot access xhprof-data: No such file or directory
奇怪了,目录呢? 使用find找下试试:
➜  /tmp$ find . -type d -name xhprof-datafind: ‘./systemd-private-bd5ddddffb9240cdad836fe13ccb096d-httpd.service-kCEghE’: Permission denied➜  /tmp$ sudo !!➜  /tmp$ sudo find . -type d -name xhprof-data./systemd-private-bd5ddddffb9240cdad836fe13ccb096d-httpd.service-kCEghE/tmp/xhprof-data
原来是放到了systemd-private-bd5ddddffb9240cdad836fe13ccb096d-httpd.service-kCEghE下面。这个是个什么鬼? 据google一下的结果,原来是systemd可以配置/tmp目录为私有目录,以防冲突而创建的。检查下配置:
➜  /tmp$ cat /usr/lib/systemd/system/httpd.service | grep PrivateTmpPrivateTmp=true
果然是有对应的这个配置。涨姿势了。特此记录。阅读全文

PHP下使用强大的imagick轻松生成组合缩略图

最近有个需求是要把多张图片组合起来生成缩略图,刚好可以用强大的imagick扩展。这里说的imagickImageMagick在PHP下的扩展。使用pecl安装起来那叫一个轻松简单 —— 一条命令就搞定:
sudo pecl install imagick
(扩展装好后还是要在php.ini中加上extension=imagick.so,然后记得重启apachePHP-fpm服务。)这个需求是要这样生成缩略图:
  1. 如果有1张图片,就直接生成这张图片的缩略图;
  2. 如果有2张图片,则一张在左边一张在右边,各一半;
  3. 如果有3张图片,则两张左边平均分配,一张独占右边;...
阅读全文

PHP中的null合并运算符

null合并运算符是一个好东西,有了它我们就能很方便的获取一个参数,并能在其为空的情况下提供一个默认值。比如在js中可以用||来搞:
function setSomething(a){a = a || 'some-default-value';// ...}
而在PHP中,可惜PHP的||总是返回truefalse,无法这样来搞。PHP7才正式加入了??这个运算符:
// 获取user参数的值(如果为空,则用'nobody')$username = $_GET['user'] ?? 'nobody';// 等价于:$username = isset($_GET['user']) ? $_GET['user'] : 'nobody';
PHP7 估计还有很长时间才能用到生产环境中,那在目前的PHP5中有没有替代方案呢?据研究,完全有个非常便捷的替代方案:
// 获取user参数的值(如果为空,则用'nobody')$username = @$_GET['user'] ?: 'nobody';// 等价于:$username = isset($_GET['user']) ? $_GET['user'] : 'nobody';
-- 运行此代码:https://3v4l.org/aDUW8瞪大了眼睛看,跟前面的PHP7的例子差不多,主要是把??替换为了?:。 这个是个什么鬼呢?其实这就是(expr1) ? (expr2) : (expr3)表达式的省略模式:
表达式 (expr1) ? (expr...
阅读全文