利用PHP的register_shutdown_function来记录PHP的输出日志,模拟析构函数
最近在做的一个项目,由于全是通过远程HTTP请求来调用PHP的接口程序。
接收到的参数和返回的内容对开发人员来说都是未知不可见的。
虽然可以通过直接在脚本中模拟请求,但由于实际环境复杂的多,调试极其不方便。
于是想是否可以写一个函数用来记录对PHP接口调用的情况。
想到以前看到过的一个PHP函数 register_shutdown_function()。
该函数的作用是注册一个函数,当PHP脚本执行完成,或者代码中调用了 exit , die 这样的代码之后,执行预先注册好的函数。
这样我们就可以在该函数中记录PHP调用执行的情况了。
简单写了下,看起来应该可以用了:
<?php
function bdebug(){ $file = "bdebug_log.txt"; if ($_REQUEST){
foreach ($_REQUEST as $k => $v) {
$request .= $k . " = " . $v . "
";
}
} foreach ($_SERVER as $k => $v) {
$server .= $k . " = " . $v . "
";
} $content = date('Y-m-d H:i:s') . " REQUEST信息:
" . $request . "
SERVER信息:
" . $server . "
"; ob_start(); function shutdown_func($file){
$content = date('Y-m-d H:i:s') . " 输出的信息:
" . ob_get_contents() . "
";
file_put_contents($file, $content, FILE_APPEND);
} register_shutdown_function('shutdown_func', dirname(__FILE__) . DIRECTORY_SEPARATOR . $file);
file_put_contents($file, $content, FILE_APPEND);
}
?>
PHP中非期望致命错误的另一种处理方式:register_shutdown_function()
程序员正确的逻辑,和良好的编程风格,对一段代码实现来说是非常重要的,既能最大限度地保证程序的准确运行,也可以在出现错误时便于调试。但也有一些意外情况的出现,导致了代码运行得到非期望的结果。当然,一些健壮的语言可以有很好的异常处理机制,比如java,但我这里要说的是在使用php进行web开发的过程中遇到的一点小问题。
日前自己参考wordpress摆弄了一个极其简易的blog程序,在实现文章编辑成功,并相指定地址发送pingback的时候,出了点小故障。期望结果是完成以上操作后,定向到文章列表页面。而出现的意外情况是,当指定的地址不可用(目标地址服务器不可访问)时,产生了一个致命错误,返回页面是错误信息,并没有如期望的跳转到文章列表。
显然,程序的健壮性不够,没有考虑到上面的异常情况。发送pingback的功能使用了php提供的套接字连接函数,在后来的测试时,若目标主机不存在,并不会导致致命错误,只是一个警告,而让人困惑的是先前的测试却出现了致命错误,可能是我修改了某些php配置引起的吧(调整了一些模块)。对于这种情况,一般用错误抑止符就可以忽略了错误信息的输出。而我想知道wordpress的处理方式是怎样的,读了它的这段实现代码后,发现其做法是在套接字连接函数前加了错误抑止符,另外将发送pingback的函数通过register_shutdown_function()注册为请求结束时的动作。这一做法给了我以启示,在php手册中,关于register_shutdown_function()函数的说明中,有这么一段注解:
Typically undefined functions cause fatal errors in PHP, but when the function called with register_shutdown_function() is undefined, an error of level E_WARNING is generated instead. Also, for reasons internal to PHP, this error will refer to Unknown() at line #0.
我们不妨将其理解为该函数可以让致命错误降级,而函数说明中有如下描述:
The registered shutdown functions are called after the request has been completed (including sending any output buffers), so it is not possible to send output to the browser using echo() or print(), or retrieve the contents of any output buffers using ob_get_contents().
那么我们就可以使用这个函数来实现类似‘@’抑止错误信息的效果了。
当然,使用这个函数来处理一些错误信息可能是得不偿失,因为这个函数的用途的初衷并不是这样的,而且,我也未能测试其执行效率,在此只是尝试另一种思路而已。
手册中还有一段说明:PHP 3 或者 PHP 4 中都没有析构函数。你可以使用 register_shutdown_function() 函数来模拟析构函数的效果。我想,这才是物尽其用吧!
如:
<?php
class Template { // 属性 public function __construct() {
// ......
if (version_compare(PHP_VERSION, '5') == -1) {
register_shutdown_function(array(&$this, '__destruct'));
}
} /**
* 析构函数
*/
public function __destruct() {
if($_COOKIE['sid']) {
return;
}
$sid = rawurlencode($this->sid);
$searcharray = array(
"/<a(s*[^>]+s*)href=(["|']?)([^"'s]+)/ies",
"/(<form.+?>)/is"
);
$replacearray = array(
"$this->_transSid('\3','<a\1href=\2')",
"\1
<input type="hidden" name="sid" value="".rawurldecode(rawurldecode(rawurldecode($sid)))."" />"
);
$content = preg_replace($searcharray, $replacearray, ob_get_contents());
ob_end_clean(); echo $content;
}
}
利用PHP的register_shutdown_function来记录PHP的输出日志,模拟析构函数的更多相关文章
- 利用php的register_shutdown_function来记录php的输出日志
最近在做的一个项目..由于全是通过远程http请求来调用php的接口程序.. 接收到的参数和返回的内容对开发人员来说都是未知不可见的.. 虽然可以通过直接在脚本中模拟请求..但由于实际环境复杂的多.. ...
- MySQL 使用tee记录语句和输出日志
在mysql命令行中,使用tee命令,可以记录语句和输出到指定文件.在debugging时会很有用.每执行一条语句,mysql都会讲执行结果刷新到指定文件.Tee功能只在交互模式生效. mysql&g ...
- Java中使用Log4j记录错误、输出日志
简介: Log4j是Apache的一个开放源代码项目,通过使用Log4j,我们可以控制日志信息输送的目的地是控制台.文件.GUI组件.甚至是套接口服务器.NT的事件记录器.UNIX Syslog守护进 ...
- "利用python进行数据分析"学习记录01
"利用python进行数据分析"学习记录 --day01 08/02 与书相关的资料在 http://github.com/wesm/pydata-book pandas 的2名字 ...
- 利用Python中的mock库对Python代码进行模拟测试
这篇文章主要介绍了利用Python中的mock库对Python代码进行模拟测试,mock库自从Python3.3依赖成为了Python的内置库,本文也等于介绍了该库的用法,需要的朋友可以参考下 ...
- 记录Windows远程登录日志(转)
1.建立一个名为RDPlog.bat的批处理文件,内容为: echo @offdate /t >>Z:\IIS\RDPlog.txt time /t >>Z:\IIS\RDPl ...
- 【记录】尝试用QEMU模拟ARM开发板去加载并运行Uboot,kernel,rootfs【转】
转自:https://www.crifan.com/try_use_qemu_emulate_arm_board_to_load_and_run_uboot_kernel_rootfs/ [背景] 手 ...
- 让FIREDAC记录数据库的异常日志
默认FIREDAC不会记录数据库的异常. 比如典型的,提交的时候,非空字段没有给值. 某些人还以为FIREDAC不能捕获数据库的异常,其实FIREDAC是可以捕获并处理数据库的异常事件的. 方法异常简 ...
- python学习记录_中断正在执行的代码,执行剪切板中的代码,键盘快捷键,魔术命令,输入和输出变量,记录输入和输出变量_
2018-03-28 00:56:39 中断正在执行的代码 无论是%run执行的脚本还是长时间运行的命令ctrl + cIn [1]: KeyboardInterrupt 执行剪切板中的代码 ctrl ...
随机推荐
- 基于Simple Image Statistics(简单图像统计,SIS)的图像二值化算法。
这是个简单的算法,是全局二值算法的一种,算法执行速度快. 算法过程简单描述如下: 对于每一个像素,做如下处理 1.计算当前像素水平和垂直方向的梯度. (two gradients are calcul ...
- PhotoShop算法原理解析系列 - 像素化---》碎片。
接着上一篇文章的热度,继续讲讲一些稍微简单的算法吧. 本文来讲讲碎片算法,先贴几个效果图吧: 这是个破坏性的滤镜,拿美女来说事是因为搞图像的人90%是男人,色色的男人. 关于碎 ...
- linux tcp超时重传实现分析
kernel version 3.18.20 1.函数调用关系 tcp_ack-> tcp_clean_rtx_queue-> tcp_ack_update_rtt-> tp-> ...
- 大牛的博客 osharp以及EF的分析
http://www.cnblogs.com/guomingfeng/ http://developer.51cto.com/art/201309/409950_all.htm
- LeetCode:Max Points on a Line
题目链接 Given n points on a 2D plane, find the maximum number of points that lie on the same straight l ...
- 我是服务的执政官-服务发现和注册工具consul简介
服务发现和注册 我们有了两个服务.服务A的IP地址是192.168.0.1,端口9001,服务B的IP地址192.168.0.2,端口9002.我们的客户端需要调用服务A和服务B,我们只需要在配置文件 ...
- 【BZOJ 1065】【Vijos 1826】【NOI 2008】奥运物流
http://www.lydsy.com/JudgeOnline/problem.php?id=1065 https://vijos.org/p/1826 好难的题啊TWT ∈我这辈子也想不出来系列~ ...
- 在渲染前获取 View 的宽高
在渲染前获取 View 的宽高 这是一个比较有意义的问题,或者说有难度的问题,问题的背景为:有时候我们需要在view渲染前去获取其宽高,典型的情形是,我们想在onCreate.onStart.onRe ...
- 解决:error: .repo/manifests/: contains uncommitted changes
repo sync同步时提示出错: error: .repo/manifests/: contains uncommitted changes 解决方法: 1.cd 进入.repo/ ...
- 修改Windows/Ubuntu/Mint多系统的默认启动顺序
打开该配置文件 sudo gedit /etc/default/grub 其中的“GRUB_DEFAULT=0”就是设置的默认启动项了.GRUB启动项是按照启动菜单依次使用数字进行索引了,起始数字为0 ...