利用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;
	}
}
posted @ 2016-07-13 00:41  52php  阅读(468)  评论(0编辑  收藏  举报