<?xml version="1.0" encoding="UTF-8" ?>
<rss version="2.0">
<channel>
<title><![CDATA[向东博客 专注WEB应用 构架之美 --- 构架之美，在于尽态极妍 | 应用之美，在于药到病除]]></title> 
<link>http://www.jackxiang.com/index.php</link> 
<description><![CDATA[赢在IT，Playin' with IT,Focus on Killer Application,Marketing Meets Technology.]]></description> 
<language>zh-cn</language> 
<copyright><![CDATA[向东博客 专注WEB应用 构架之美 --- 构架之美，在于尽态极妍 | 应用之美，在于药到病除]]></copyright>
<item>
<link>http://www.jackxiang.com/post//</link>
<title><![CDATA[[转]set_error_handler() 重要用法 ]]></title> 
<author>jack &lt;xdy108@126.com&gt;</author>
<category><![CDATA[Php/Js/Shell/Go]]></category>
<pubDate>Thu, 04 Jul 2013 08:17:19 +0000</pubDate> 
<guid>http://www.jackxiang.com/post//</guid> 
<description>
<![CDATA[ 
	背景：<br/>群里有兄弟在问：<br/>我在PHP.ini里 display=off屏蔽了错误，然后把错误信息 写入到LOG里<br/>怎么搞？<br/>一）<br/>set_exception_handler<br/>set_error_handler<br/>二）php.ini里配置：<br/>log_errors = On<br/>error_log = /data/logs/php_error.log<br/><br/><br/> set_error_handler这个函数的作用是为了防止错误路径泄露<br/>何为错误路径泄露呢？<br/>我们写程序，难免会有问题（是经常会遇到问题 :razz: ），而PHP遇到错误时，就会给出出错脚本的位置、行数和原因<br/>有很多人说，这并没有什么大不了。确实，在调试程序阶段，这确实是没啥的，而且我认为给出错误路径是必要的。<br/>但泄露了实际路径的后果是不堪设想的，对于某些入侵者，这个信息可是非常重要，而事实上现在有很多的服务器都存在这个问题。<br/>有些网管干脆把PHP配置文件中的display_errors设置为Off来解决（貌似我们就是这样做的），但本人认为这个方法过于消极。<br/>有些时候，我们的确需要PHP返回错误的信息以便调试。而且在出错时也可能需要给用户一个交待，甚至导航到另一页面。<br/>那么，有啥解决办法呢？<br/>PHP从4.1.0开始提供了自定义错误处理句柄的功能函数set_error_handler()，但很少数脚本编写者知道。<br/>set_error_handler的使用方法如下：<br/>string set_error_handler ( callback error_handler [, int error_types])&nbsp;&nbsp; <br/>现在我们就用自定义的错误处理把实际路径过滤掉。<br/>如：假设有一个变量$admin，我们是用来判断访问者是否是管理员的（可以通过IP或者登录的用户id来做这个判断）<br/>//admin为管理员的身份判定，true为管理员。&nbsp;&nbsp;<br/>//自定义的错误处理函数一定要有这４个输入变量$errno,$errstr,$errfile,$errline，否则无效。&nbsp;&nbsp;<br/>function my_error_handler($errno,$errstr,$errfile,$errline)&nbsp;&nbsp;<br/>&#123;&nbsp;&nbsp;<br/>&nbsp;&nbsp;&nbsp;&nbsp;//如果不是管理员就过滤实际路径&nbsp;&nbsp;<br/>&nbsp;&nbsp;&nbsp;&nbsp;if(!admin)&nbsp;&nbsp;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#123;&nbsp;&nbsp;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$errfile=str_replace(getcwd(),&quot;&quot;,$errfile);&nbsp;&nbsp;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$errstr=str_replace(getcwd(),&quot;&quot;,$errstr);&nbsp;&nbsp;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#125;&nbsp;&nbsp;<br/>&nbsp;&nbsp;&nbsp;&nbsp;switch($errno)&nbsp;&nbsp;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#123;&nbsp;&nbsp;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;case E_ERROR:&nbsp;&nbsp;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;echo &quot;ERROR: [ID $errno] $errstr (Line: $errline of $errfile) &#92;n&quot;;&nbsp;&nbsp;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;echo &quot;程序已经停止运行，请联系管理员。&quot;;&nbsp;&nbsp;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//遇到Error级错误时退出脚本&nbsp;&nbsp;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;exit;&nbsp;&nbsp;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;break;&nbsp;&nbsp;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;case E_WARNING:&nbsp;&nbsp;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;echo &quot;WARNING: [ID $errno] $errstr (Line: $errline of $errfile) &#92;n&quot;;&nbsp;&nbsp;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;break;&nbsp;&nbsp;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;default:&nbsp;&nbsp;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//不显示Notice级的错误&nbsp;&nbsp;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;break;&nbsp;&nbsp;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#125;&nbsp;&nbsp;<br/>&#125;&nbsp;&nbsp;<br/>这样就自定义了一个错误处理函数，那么怎么把错误的处理交给这个自定义函数呢？<br/>// 应用到类&nbsp;&nbsp;<br/>set_error_handler(array(&amp;$this,&quot;appError&quot;));&nbsp;&nbsp;<br/>//示例的做法&nbsp;&nbsp;<br/>set_error_handler(&quot;my_error_handler&quot;);<br/>so easy，这样，就可以很好地解决安全和调试方便的矛盾了。而且你还可以花点心思，使错误提示更加美观以配合网站的风格。<br/>原作者给出了两点需要注意的地方，我也放出来吧，希望引起广大同胞们的注意：<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;E_ERROR、E_PARSE、E_CORE_ERROR、E_CORE_WARNING、 E_COMPILE_ERROR、E_COMPILE_WARNING是不会被这个句柄处理的，也就是会用最原始的方式显示出来。不过出现这些错误都是编 译或PHP内核出错，在通常情况下不会发生。<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;使用set_error_handler()后，error_reporting ()将会失效。也就是所有的错误（除上述的错误）都会交给自定义的函数处理。<br/>最后，原作者又给出了一个示例（真是个认真负责的好人哈。呵呵）<br/>//先定义一个函数，也可以定义在其他的文件中，再用require()调用&nbsp;&nbsp;<br/>function myErrorHandler($errno, $errstr, $errfile, $errline)&nbsp;&nbsp;<br/>&#123;&nbsp;&nbsp;<br/>　　　　　//为了安全起见，不暴露出真实物理路径，下面两行过滤实际路径&nbsp;&nbsp;<br/>&nbsp;&nbsp;&nbsp;&nbsp;$errfile=str_replace(getcwd(),&quot;&quot;,$errfile);&nbsp;&nbsp;<br/>&nbsp;&nbsp;&nbsp;&nbsp;$errstr=str_replace(getcwd(),&quot;&quot;,$errstr);&nbsp;&nbsp;<br/>&nbsp;&nbsp;&nbsp;&nbsp;switch ($errno) &#123;&nbsp;&nbsp;<br/>&nbsp;&nbsp;&nbsp;&nbsp;case E_USER_ERROR:&nbsp;&nbsp;<br/>&nbsp;&nbsp;&nbsp;&nbsp; echo &quot;&lt;b&gt;My ERROR&lt;/b&gt; [$errno] $errstr&lt;br /&gt;&#92;n&quot;;&nbsp;&nbsp;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;echo &quot;&nbsp;&nbsp;Fatal error on line $errline in file $errfile&quot;;&nbsp;&nbsp;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;echo &quot;, PHP &quot; . PHP_VERSION . &quot; (&quot; . PHP_OS . &quot;)&lt;br /&gt;&#92;n&quot;;&nbsp;&nbsp;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;echo &quot;Aborting...&lt;br /&gt;&#92;n&quot;;&nbsp;&nbsp;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;exit(1);&nbsp;&nbsp;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;break;&nbsp;&nbsp;<br/>&nbsp;&nbsp;&nbsp;&nbsp;case E_USER_WARNING:&nbsp;&nbsp;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;echo &quot;&lt;b&gt;My WARNING&lt;/b&gt; [$errno] $errstr&lt;br /&gt;&#92;n&quot;;&nbsp;&nbsp;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;break;&nbsp;&nbsp;<br/>&nbsp;&nbsp;&nbsp;&nbsp;case E_USER_NOTICE:&nbsp;&nbsp;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;echo &quot;&lt;b&gt;My NOTICE&lt;/b&gt; [$errno] $errstr&lt;br /&gt;&#92;n&quot;;&nbsp;&nbsp;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;break;&nbsp;&nbsp;<br/>&nbsp;&nbsp;&nbsp;&nbsp;default:&nbsp;&nbsp;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;echo &quot;Unknown error type: [$errno] $errstr&lt;br /&gt;&#92;n&quot;;&nbsp;&nbsp;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;break;&nbsp;&nbsp;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#125;&nbsp;&nbsp;<br/>&nbsp;&nbsp;&nbsp;&nbsp;/* Don&#039;t execute PHP internal error handler */&nbsp;&nbsp;<br/>&nbsp;&nbsp;&nbsp;&nbsp;return true;&nbsp;&nbsp;<br/>&#125;&nbsp;&nbsp;<br/>//下面开始连接MYSQL服务器，我们故意指定MYSQL端口为3333,实际为3306。&nbsp;&nbsp;<br/>$link_id=@mysql_pconnect(&quot;localhost:3333&quot;,&quot;root&quot;,&quot;password&quot;);&nbsp;&nbsp;<br/>set_error_handler(myErrorHandler);&nbsp;&nbsp;<br/>if (!$link_id) &#123;&nbsp;&nbsp;<br/>&nbsp;&nbsp;&nbsp;&nbsp;trigger_error(&quot;出错了&quot;, E_USER_ERROR);&nbsp;&nbsp;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#125;&nbsp;&nbsp;<br/>嗯，根据上面的那些解释，以及原作者认真负责的态度，我想如果我还学不会这个set_error_handler函数，那么我真该去撞墙了。 :cool:<br/>好了，总结一下，下面是 set_error_handler 三种用法：<br/>class CallbackClass &#123;&nbsp;&nbsp;<br/>&nbsp;&nbsp; function CallbackFunction() &#123;&nbsp;&nbsp;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // refers to $this&nbsp;&nbsp;<br/>&nbsp;&nbsp; &#125;&nbsp;&nbsp;<br/>&nbsp;&nbsp; function StaticFunction() &#123;&nbsp;&nbsp;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // doesn&#039;t refer to $this&nbsp;&nbsp;<br/>&nbsp;&nbsp; &#125;&nbsp;&nbsp;<br/>&#125;&nbsp;&nbsp;<br/>function NonClassFunction($errno, $errstr, $errfile, $errline) &#123;&nbsp;&nbsp;<br/>&#125;&nbsp;&nbsp;<br/>// 三种方法如下:&nbsp;&nbsp;<br/>1: set_error_handler(&#039;NonClassFunction&#039;);&nbsp;&nbsp;// 直接转到一个普通的函数 NonClassFunction&nbsp;&nbsp;<br/>2: set_error_handler(array(&#039;CallbackClass&#039;, &#039;StaticFunction&#039;)); // 转到 CallbackClass 类下的静方法 StaticFunction&nbsp;&nbsp;<br/>&nbsp;&nbsp;/*第一个参数为数组，类名、方法名*/<br/>3: $o =&amp; new CallbackClass();&nbsp;&nbsp;&nbsp;&nbsp;//地址引用<br/>&nbsp;&nbsp;&nbsp;&nbsp;set_error_handler(array($o, &#039;CallbackFunction&#039;));&nbsp;&nbsp;// 转到类的构造函数，其实本质上跟下面的第四条一样。&nbsp;&nbsp;<br/>4. $o = new CallbackClass();&nbsp;&nbsp;<br/>// The following may also prove useful:&nbsp;&nbsp;<br/>class CallbackClass &#123;&nbsp;&nbsp;<br/>&nbsp;&nbsp; function CallbackClass() &#123;&nbsp;&nbsp;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; set_error_handler(array(&amp;$this, &#039;CallbackFunction&#039;)); // the &amp; is important&nbsp;&nbsp;<br/>&nbsp;&nbsp; &#125;&nbsp;&nbsp;<br/>&nbsp;&nbsp; function CallbackFunction() &#123;&nbsp;&nbsp;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // refers to $this&nbsp;&nbsp;<br/>&nbsp;&nbsp; &#125;&nbsp;&nbsp;<br/>&#125;&nbsp;&nbsp;<br/>来自：http://blog.csdn.net/haha00217/article/details/7674250
]]>
</description>
</item><item>
<link>http://www.jackxiang.com/post//#blogcomment</link>
<title><![CDATA[[评论] [转]set_error_handler() 重要用法 ]]></title> 
<author> &lt;user@domain.com&gt;</author>
<category><![CDATA[评论]]></category>
<pubDate>Thu, 01 Jan 1970 00:00:00 +0000</pubDate> 
<guid>http://www.jackxiang.com/post//#blogcomment</guid> 
<description>
<![CDATA[ 
	
]]>
</description>
</item>
</channel>
</rss>