<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>风雪之隅</title>
	<atom:link href="http://www.laruence.com/feed" rel="self" type="application/rss+xml" />
	<link>http://www.laruence.com</link>
	<description>PHP应用,PHP源码分析,Zend引擎分析,Web相关技术研究,Web技术分享 - 左手代码 右手诗</description>
	<lastBuildDate>Wed, 18 Aug 2010 09:07:34 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>将PHP Manual融入(g)Vim</title>
		<link>http://www.laruence.com/2010/08/18/1718.html</link>
		<comments>http://www.laruence.com/2010/08/18/1718.html#comments</comments>
		<pubDate>Wed, 18 Aug 2010 08:46:20 +0000</pubDate>
		<dc:creator>雪候鸟</dc:creator>
				<category><![CDATA[PHP应用]]></category>
		<category><![CDATA[随笔]]></category>
		<category><![CDATA[gvim]]></category>
		<category><![CDATA[manual]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[vim]]></category>
		<category><![CDATA[手册]]></category>

		<guid isPermaLink="false">http://www.laruence.com/?p=1718</guid>
		<description><![CDATA[首先说个题外话: Vim发布<a href="http://www.vim.org/" target="_blank">7.3</a>了..

    在翻看Vim插件的时候, 发现了一个比较有意思的应用(非插件): 把PHP的手册融如Vim中, 在Vim中, 按"K", 就可以跳转到光标下函数的手册说明...]]></description>
			<content:encoded><![CDATA[<div class="copyright" >
<ul  style="padding-left:1em;font-size:85%;padding-left:1em;font-size:85%;">
<li>作者: laruence(<a href="http://www.laruence.com"  title="风雪之隅"  target="_blank" >http://www.laruence.com</a>)</li>
<li>本文地址: <a href="http://www.laruence.com/2010/08/18/1718.html"  title="Permanet Link to 将PHP Manual融入(g)Vim" >http://www.laruence.com/2010/08/18/1718.html</a></li>
<li>转载请注明出处 </li>
</ul></div>
<p>
    首先说个题外话: Vim发布<a href="http://www.vim.org/"  target="_blank" >7.3</a>了..</p>
<p>    在翻看Vim插件的时候, 发现了一个比较有意思的应用(非插件): 把PHP的手册融如Vim中, 在Vim中, 按&#8221;K&#8221;, 就可以跳转到光标下函数的手册说明&#8230;</p>
<p>    1. 首先, 下载特殊定制的PHP手册(包含PHP5.3的所有函数) : <a href="http://www.interpotential.com/downloads/vim/vim-php-manual.tar.gz"  target="_blank" >vim-php-manual.tar.gz</a></p>
<p>    2. 把下载的文件解压缩, 放置到一个目录, 比如/tmp/phpmuanul(windows下比如:&#8221;d:/phpmanual&#8221;).</p>
<p>    3. 配置vimrc(linux下是.vimrc,windows下是_vimrc), 把phpmanual目录添加到runtimepath(稍后解释为什么).</p>
<p>    4. 配置vimrc, 使得keywordprg=&#8221;help&#8221;. 在我的机器上, keywordprg默认是!man, 大多数时候, 我还是希望可以直接man到linux下的标准函数库, 所以我使用(在vimrc文件中):</p>
<pre name="code"  class="sh_bash"  linenum="off"   style="background: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:Monacobackground: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:MonacoConsolasConsolasCourierCouriermonospace;monospace;">
autocmd BufNewFile,Bufread *.ros,*.inc,*.php set keywordprg=&quot;help&quot;
</pre>
<p>    或者也可以写在vim目录下的ftplugin下的php.vim(如果没有新建), 这样在ft为php的时候,这个配置脚本就会被加载.</p>
<p>  至于说, 为什么要把phpmanual目录添加到runtimepath, 是因为:</p>
<pre name="code"  class="sh_bash"  linenum="off"   style="background: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:Monacobackground: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:MonacoConsolasConsolasCourierCouriermonospace;monospace;">
When no argument is given to :help the file given with the 'helpfile' option
will be opened.  Otherwise the specified tag is searched for in all &quot;doc/tags&quot;
files in the directories specified in the 'runtimepath' option.
</pre>
<p>   意思就是说, 在vim中, 调用help的时候, help会去所有的runtimpath下的doc目录中寻找tags文件, 来寻找要查找的帮助关键字.</p>
<p>   在我们下载的vim-php-manual.tar.gz文件中, 就包含了doc/tags这样的文件目录结构, 所以只要把phpmanual目录加入runtimepath, 并且设置keywordprg为vim的help, 就可以实现在光标处按&#8221;K&#8221;跳转到函数手册了.<br/>
<div id="attachment_1721"  class="wp-caption aligncenter"  style="width: 310px" ><a href="http://www.laruence.com/wp-content/uploads/vim_phpmanul.png" ><img src="http://www.laruence.com/wp-content/uploads/vim_phpmanul-300x185.png"  alt=""  title="vim_phpmanul"  width="300"  height="185"  class="size-medium wp-image-1721" /></a><p class="wp-caption-text" >使用截图</p></div></p>
<p>    最后,补充一点, 如果在使用的时候,Vim提示你:</p>
<pre name="code"  class="sh_php"  linenum="off"   style="background: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:Monacobackground: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:MonacoConsolasConsolasCourierCouriermonospace;monospace;">
 tags file not sorted
</pre>
<p>   那你就用vim打开phpmanual/doc/tags, 然后%sort一下就可以了&#8230;<script type="text/javascript"  src="http://www.laruence.com/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_bash.js" ></script><script type="text/javascript"  src="http://www.laruence.com/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_bash.js" ></script><script type="text/javascript"  src="http://www.laruence.com/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_php.js" ></script></p>
<hr/><h2>Comments</h2><ul  style="padding-left:1em;font-size:85%;padding-left:1em;font-size:85%;"><li><a href="http://www.laruence.com/2010/08/18/1718.html#comment-3089" >2010/08/18</a>, <a href="http://www.youyuge.com"  rel="external nofollow"  class="url" >xiaokai</a> writes: 下班回家试试..</li><li><a href="http://www.laruence.com/2010/08/18/1718.html#comment-3090" >2010/08/18</a>, <a href="http://www.felix021.com"  rel="external nofollow"  class="url" >felix021</a> writes: 感谢分享！ 
.tar.gz下载有点儿慢。

另外，keywordprg应该是 :help
autocmd FileType php set keywordprg=:help</li><li><a href="http://www.laruence.com/2010/08/18/1718.html#comment-3091" >2010/08/18</a>, <a href="http://www.laruence.com"  rel="external nofollow"  class="url" >雪候鸟</a> writes: @felix021 :help和"help"(有引号)都可, :)</li><li><a href="http://www.laruence.com/2010/08/18/1718.html#comment-3092" >2010/08/18</a>, simplechen writes: 兄弟你是用VIM的老手了，能否分享一下你的VIM配置。：） 多谢！</li><li><a href="http://www.laruence.com/2010/08/18/1718.html#comment-3094" >2010/08/19</a>, <a href="http://topsy.com/www.laruence.com/2010/08/18/1718.html?utm_source=pingback&amp;utm_campaign=L2"  rel="external nofollow"  class="url" >Tweets that mention 将PHP Manual融入(g)Vim | 风雪之隅 -- Topsy.com</a> writes: [...] This post was mentioned on Twitter by 惠新宸, glemir and 惠新宸, Wing. Wing said: 說 http://www.plurk.com/p/70diq1 ([rep])@jaceju : http://tinyurl.com/25dqjgl (将PHP Manual融入（g）Vim) http://plurk.com/p/70igkh [...]</li><li><a href="http://www.laruence.com/2010/08/18/1718.html#comment-3097" >2010/08/21</a>, <a href="http://www.zhangabc.com"  rel="external nofollow"  class="url" >张二</a> writes: 呵呵，试了一下，果然V5，比较懒，set runtimepath发现.vim/doc已经包含在runtimepath变量中了，由于直接cd ~/.vim,然后解压了鸟哥的包（好多文件),然后设置了一下.vimrc……很好用哦。</li><li><a href="http://www.laruence.com/2010/08/18/1718.html#comment-3103" >2010/08/22</a>, <a href="http://www.gugeqq.com"  rel="external nofollow"  class="url" >谷哥QQ</a> writes: 感谢分享！</li><li><a href="http://www.laruence.com/2010/08/18/1718.html#comment-3105" >2010/08/23</a>, <a href="http://www.nflfootballjerseys"  rel="external nofollow"  class="url" >nfl football jerseys</a> writes: 博主绝对是VIM高手，提供的很详细，刚试了一下，很好用，谢谢了</li><li><a href="http://www.laruence.com/2010/08/18/1718.html#comment-3112" >2010/08/25</a>, <a href="http://www.airmaxtrainer.com"  rel="external nofollow"  class="url" >air max shoes</a> writes: 是挺慢的 不过很好用哦！</li><li><a href="http://www.laruence.com/2010/08/18/1718.html#comment-3123" >2010/08/30</a>, <a href="http://www.js4j.com/"  rel="external nofollow"  class="url" >技术网</a> writes: 还没试用，先谢谢分享</li><li><a href="http://www.laruence.com/2010/08/18/1718.html#comment-3132" >2010/09/01</a>, <a href="http://www.olc.com.tr"  rel="external nofollow"  class="url" >Yurtdışı Eğitim</a> writes: Is this web site availible in English?</li></ul><hr/><small  style="font-size:85%;font-size:85%;">Copyright &copy; 2010 <a href="http://www.laruence.com"  target="_blank" >风雪之隅</a> 版权所有, 转载务必注明. 该Feed只供个人使用, 禁止未注明的转载或商业应用. 非法应用的, 一切法律后果自负. 如有问题, 可发E-mail至my at laruence.com.(Digital Fingerprint: 73540ba0a1738d7d07d4b6038d5615e2)</small>]]></content:encoded>
			<wfw:commentRss>http://www.laruence.com/2010/08/18/1718.html/feed</wfw:commentRss>
		<slash:comments>11</slash:comments>
		</item>
		<item>
		<title>深入理解PHP原理之异常机制</title>
		<link>http://www.laruence.com/2010/08/03/1697.html</link>
		<comments>http://www.laruence.com/2010/08/03/1697.html#comments</comments>
		<pubDate>Tue, 03 Aug 2010 14:23:38 +0000</pubDate>
		<dc:creator>雪候鸟</dc:creator>
				<category><![CDATA[PHP应用]]></category>
		<category><![CDATA[PHP源码分析]]></category>
		<category><![CDATA[php原理]]></category>
		<category><![CDATA[PHP异常]]></category>
		<category><![CDATA[set_error_handler]]></category>
		<category><![CDATA[set_exception_handler]]></category>
		<category><![CDATA[ZEND_HANDLE_EXCEPTION]]></category>

		<guid isPermaLink="false">http://www.laruence.com/?p=1697</guid>
		<description><![CDATA[  PHP的异常机制的原理是什么?

  在PHP每一个可独立执行的op array最后的ZEND_HANDLE_EXCEPTION是用来干什么呢?]]></description>
			<content:encoded><![CDATA[<div class="copyright" >
<ul  style="padding-left:1em;font-size:85%;padding-left:1em;font-size:85%;">
<li>作者: laruence(<a href="http://www.laruence.com"  title="风雪之隅"  target="_blank" >http://www.laruence.com</a>)</li>
<li>本文地址: <a href="http://www.laruence.com/2010/08/03/1697.html"  title="Permanet Link to 深入理解PHP原理之异常机制" >http://www.laruence.com/2010/08/03/1697.html</a></li>
<li>转载请注明出处 </li>
</ul></div>
<p>
    PHP的异常机制的原理是什么?</p>
<p>    在PHP每一个可独立执行的op array最后的ZEND_HANDLE_EXCEPTION是用来干什么呢?</p>
<p>    让我们从一个问题说起, 上周的时候, blue5tar提了一个问题:&#8221;对于下面的代码, onError明明执行了, 但是onException却没有执行, 为什么?&#8221;. </p>
<pre name="code"  class="sh_php"  linenum="off"   style="background: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:Monacobackground: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:MonacoConsolasConsolasCourierCouriermonospace;monospace;">
&lt;?php
function onError($errCode, $errMesg, $errFile, $errLine) {
    echo &quot;Error Occurred\n&quot;;
    throw new Exception($errMesg);
}

function onException($e) {
    echo $e-&gt;getMessage();
}

set_error_handler(&quot;onError&quot;);

set_exception_handler(&quot;onException&quot;);

/* 我从不会以我的名字命名文件, 所以这个文件不存在 */
require(&quot;laruence.php&quot;);
</pre>
<p>	运行结果:</p>
<pre name="code"  class="sh_bash"  linenum="off"   style="background: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:Monacobackground: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:MonacoConsolasConsolasCourierCouriermonospace;monospace;">
Error Occurred
PHP Fatal error:  main(): Failed opening required 'laruence.php'
</pre>
<p>	首先, 我们要知道, Require在包含一个找不到的问题的时候, 会前后抛出俩个错误, </p>
<pre name="code"  class="sh_bash"  linenum="off"   style="background: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:Monacobackground: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:MonacoConsolasConsolasCourierCouriermonospace;monospace;">
1. WARNING : 在PHP试图打开这个文件的时候抛出.
2. E_COMPILE_ERROR : 从PHP打开文件的函数返回失败以后抛出.
</pre>
<p>	而我们知道, set_error_handler是不能捕获E_COMPILE_ERROR错误的:</p>
<blockquote><p>
The following error types cannot be handled with a user defined function: E_ERROR, E_PARSE, E_CORE_ERROR, E_CORE_WARNING, E_COMPILE_ERROR, E_COMPILE_WARNING, and most of E_STRICT raised in the file where set_error_handler() is called.
</p></blockquote>
<p>	所以, 在onError中, 只能捕获到第一个WARNING错误,  而在onError中抛出的异常, 为什么没有被默认exception_handler捕获呢? </p>
<p>    这就要说说PHP的异常机制了.</p>
<p>	了解opcode(<a href="http://www.laruence.com/2008/06/18/221.html" >深入理解PHP原理之Opcodes</a>的同学都知道, 在PHP5.3以前, 每一个可独立运行的op array(文件, 函数, 方法)的最后一条opcode都是ZEND_HANDLE_EXCEPTION, 而这个opcode是做什么用的呢?</p>
<p>	原来在PHP中, 当有异常被throw的时候, 会跳到每一个op array的最后一行,  来执行这条ZEND_HANDLE_EXCEPTION, 伪码如下:</p>
<pre name="code"  class="sh_c"  linenum="off"   style="background: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:Monacobackground: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:MonacoConsolasConsolasCourierCouriermonospace;monospace;">
void on_throw_exception(zval *exception TSRMLS_DC) {
1. 判断是否已经有异常抛出
2. 记录exception
3. 记录下一条要执行的op line的序号
4. 下一条要执行的op line序号 = 当前op array的最后一条
}
</pre>
<p>	恩, 就和改写ip寄存器一样, 改写下一条要执行的op line的序号, 就改变了程序的流向, 这样, 就会进入到了ZEND_HANDLE_EXCEPTION的处理逻辑中.</p>
<p>	而在ZEND_HANDLE_EXCEPTION中, 会判断这个异常是否在try catch中, </p>
<pre name="code"  class="sh_bash"  linenum="off"   style="background: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:Monacobackground: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:MonacoConsolasConsolasCourierCouriermonospace;monospace;">
如果是    则把下一条要执行的op line, 置为第一个catch的op line, 并继续执行.
如果不是  则销毁一些不需要的变量, 和opline,  然后直接结束执行过程.
</pre>
<p>    有的同学要问了:&#8221;那set_exception_handler设置的异常默认处理函数(user_exception_handler)什么时候起作用呢?&#8221; </p>
<p>    恩, 是在执行完成退出执行LOOP以后才判断是否有默认异常处理函数, 如果有才调用:</p>
<pre name="code"  class="sh_c"  linenum="off"   style="background: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:Monacobackground: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:MonacoConsolasConsolasCourierCouriermonospace;monospace;">
//执行
zend_execute(EG(active_op_array) TSRMLS_CC);
if (EG(exception)) {
	if (EG(user_exception_handler)) {
		调用用户定义的默认异常处理函数
	} else {
		未捕获的异常
	}
} else {
	没有异常
}
destroy_op_array(EG(active_op_array) TSRMLS_CC);
efree(EG(active_op_array));
</pre>
<p><div id="attachment_1710"  class="wp-caption aligncenter"  style="width: 280px" ><a href="http://www.laruence.com/wp-content/uploads/PHP-exception-cycle.png" ><img src="http://www.laruence.com/wp-content/uploads/PHP-exception-cycle-270x300.png"  alt="PHP异常流程"  title="PHP异常流程"  width="270"  height="300"  class="size-medium wp-image-1710" /></a><p class="wp-caption-text" >PHP异常流程</p></div><br/>
       注: 图中有一处不严谨, 即在确定是否最后一个catch块的时候, 会同时判断(is_a), 如果是才进入最后一个catch块执行.</p>
<p>	而PHP在遇到Fatal Error的时候, 会直接zend_bailout, 而zend_bailout会导致程序流程直接跳过上面代码段, 也可以理解为直接exit了(longjmp), 这就导致了user_exception_handler没有机会发生作用.</p>
<p>	了解到这些, 我想文章开头的问题的为什么? 也就很清晰了吧? </p>
<p>       最后, 关于ZEND_HANDLE_EXCEPTION, 也许有同学会有疑问: 如果是这样, 那为什么每一个可独立执行的op array最后都有这个ZEND_HANDLE_EXCEPTION呢? 最简单的, 如果一个函数中不会throw, 那么这个opcode 是明显不需要的啊?  嘿嘿, 你很聪明, PHP 5.3开始, 已经按照你的想法调整了.. 只有在throw时刻, 才会动态的生成ZEND_HANDLE_EXCEPTION opline. </p>
<p><a href="http://php.net/ChangeLog-5.php" >PHP5 changelog</a>:</p>
<blockquote><p>Changed exception handling. Now each op_array doesn&#8217;t contain ZEND_HANDLE_EXCEPTION opcode in the end. (Dmitry)</p></blockquote>
<p><script type="text/javascript"  src="http://www.laruence.com/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_php.js" ></script><script type="text/javascript"  src="http://www.laruence.com/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_bash.js" ></script><script type="text/javascript"  src="http://www.laruence.com/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_bash.js" ></script><script type="text/javascript"  src="http://www.laruence.com/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_c.js" ></script><script type="text/javascript"  src="http://www.laruence.com/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_bash.js" ></script><script type="text/javascript"  src="http://www.laruence.com/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_c.js" ></script></p>
<hr/><h2>Comments</h2><ul  style="padding-left:1em;font-size:85%;padding-left:1em;font-size:85%;"><li><a href="http://www.laruence.com/2010/08/03/1697.html#comment-3036" >2010/08/03</a>, <a href="http://www.trylife.cn"  rel="external nofollow"  class="url" >trylife</a> writes: 沙发后再仔细看</li><li><a href="http://www.laruence.com/2010/08/03/1697.html#comment-3037" >2010/08/04</a>, <a href="http://moontoc.com"  rel="external nofollow"  class="url" >MoontoC</a> writes: 对于解析错误致命错误之类,只有shutdown function可以接收或者拦截

但是理想条件下是该函数是绝对的第一个shutdown function, 不然会变得无法预估发生什么</li><li><a href="http://www.laruence.com/2010/08/03/1697.html#comment-3065" >2010/08/06</a>, <a href="http://www.js4j.com/"  rel="external nofollow"  class="url" >技术世界</a> writes: 看不懂！~~~~~~</li><li><a href="http://www.laruence.com/2010/08/03/1697.html#comment-3068" >2010/08/08</a>, <a href="http://www.jaceju.net/blog/?p=1328"  rel="external nofollow"  class="url" >網站製作學習誌 &raquo; [Web] 連結分享</a> writes: [...] 深入理解PHP原理之异常机制 [...]</li><li><a href="http://www.laruence.com/2010/08/03/1697.html#comment-3070" >2010/08/08</a>, simplechen writes: 流程图是用什么工具做的？google docs 中的绘图吗？</li><li><a href="http://www.laruence.com/2010/08/03/1697.html#comment-3087" >2010/08/18</a>, 烂页 writes: 鸟哥威武。我基本看后不留言。今天还是留言吧！哈哈！</li><li><a href="http://www.laruence.com/2010/08/03/1697.html#comment-3101" >2010/08/21</a>, <a href="http://www.coderbolg.com"  rel="external nofollow"  class="url" >蓝色夏威夷</a> writes: 确实很深奥！</li><li><a href="http://www.laruence.com/2010/08/03/1697.html#comment-3104" >2010/08/22</a>, <a href="http://www.taobaowenda.com"  rel="external nofollow"  class="url" >淘宝问答</a> writes: 异常机制</li><li><a href="http://www.laruence.com/2010/08/03/1697.html#comment-3111" >2010/08/24</a>, <a href="http://www.airmaxtrainer.com"  rel="external nofollow"  class="url" >air max shoes</a> writes: 好难懂 还是看不懂！</li><li><a href="http://www.laruence.com/2010/08/03/1697.html#comment-3116" >2010/08/26</a>, <a href="http://www.edhardyonlineshop.net"  rel="external nofollow"  class="url" >ShopEDHardyOnline</a> writes: 菜鸟来向博主学习了^</li><li><a href="http://www.laruence.com/2010/08/03/1697.html#comment-3118" >2010/08/26</a>, xiaobao writes: 上面的流程图对吗？
如果没有一个catch捕捉到异常，那么还会判断有没有exception_handler,如果没有，才最终终止执行，弹出uncautch...</li><li><a href="http://www.laruence.com/2010/08/03/1697.html#comment-3121" >2010/08/26</a>, <a href="http://www.laruence.com"  rel="external nofollow"  class="url" >laruence</a> writes: @xiaobao 默认函数的执行是在执行器完成后, 文章中有叙及.</li><li><a href="http://www.laruence.com/2010/08/03/1697.html#comment-3127" >2010/08/31</a>, xiaobao writes: getMessage();
}
 
set_error_handler("onError");
 
set_exception_handler("onException");
 
/* 我从不会以我的名字命名文件, 所以这个文件不存在 */
require("laruence.php");

?&gt;

上面的代码会输出什么呢？

我试了下，结果抛出的异常也被捕捉到了！！

什么原因，能解释下吗？万分感谢。。</li><li><a href="http://www.laruence.com/2010/08/03/1697.html#comment-3130" >2010/08/31</a>, <a href="http://www.laruence.com"  rel="external nofollow"  class="url" >laruence</a> writes: @xiaobao 哦? 你的PHP是什么版本?</li></ul><hr/><small  style="font-size:85%;font-size:85%;">Copyright &copy; 2010 <a href="http://www.laruence.com"  target="_blank" >风雪之隅</a> 版权所有, 转载务必注明. 该Feed只供个人使用, 禁止未注明的转载或商业应用. 非法应用的, 一切法律后果自负. 如有问题, 可发E-mail至my at laruence.com.(Digital Fingerprint: 73540ba0a1738d7d07d4b6038d5615e2)</small>]]></content:encoded>
			<wfw:commentRss>http://www.laruence.com/2010/08/03/1697.html/feed</wfw:commentRss>
		<slash:comments>14</slash:comments>
		</item>
		<item>
		<title>注意PHP对字符串的递增运算</title>
		<link>http://www.laruence.com/2010/07/30/1682.html</link>
		<comments>http://www.laruence.com/2010/07/30/1682.html#comments</comments>
		<pubDate>Fri, 30 Jul 2010 08:04:09 +0000</pubDate>
		<dc:creator>雪候鸟</dc:creator>
				<category><![CDATA[PHP应用]]></category>
		<category><![CDATA[随笔]]></category>
		<category><![CDATA[increment string]]></category>
		<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">http://www.laruence.com/?p=1682</guid>
		<description><![CDATA[ 有同学问了一个问题:
<coolcode lang="php" linenum="off">
<?php
for($i = 'A'; $i <= 'Z'; $i++) {
    echo $i;
}
</coolcode>
    输出是啥?
   
   说个题外话: <a href="http://www.laruence.com">Blog</a>现在支持订阅评论了, 同学们有提问以后等我回答的, 可以在留言提问的时候, 选择:Notify me of followup comments via e-mail]]></description>
			<content:encoded><![CDATA[<div class="copyright" >
<ul  style="padding-left:1em;font-size:85%;padding-left:1em;font-size:85%;">
<li>作者: laruence(<a href="http://www.laruence.com"  title="风雪之隅"  target="_blank" >http://www.laruence.com</a>)</li>
<li>本文地址: <a href="http://www.laruence.com/2010/07/30/1682.html"  title="Permanet Link to 注意PHP对字符串的递增运算" >http://www.laruence.com/2010/07/30/1682.html</a></li>
<li>转载请注明出处 </li>
</ul></div>
<p>
    有同学问了一个问题:</p>
<pre name="code"  class="sh_php"  linenum="off"   style="background: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:Monacobackground: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:MonacoConsolasConsolasCourierCouriermonospace;monospace;">
&lt;?php
for($i = 'A'; $i &lt;= 'Z'; $i++) {
    echo $i;
}
</pre>
<p>    输出是啥?</p>
<p>   输出是:</p>
<blockquote><p>ABCDEFGHIJKLMNOPQRSTUVWXYZAAABACADAEAFAGAHAIAJAKALAMANAOAPAQARAS&#8230;&#8230;.</p></blockquote>
<p>    为啥?</p>
<p>    其实很简单,  PHP的手册中也有说明, 只不过恐怕很多人不会一章一节的把手册仔细阅读一遍:</p>
<blockquote><p>
     PHP follows Perl&#8217;s convention when dealing with arithmetic operations on character variables and not C&#8217;s. For example, in Perl &#8216;Z&#8217;+1 turns into &#8216;AA&#8217;, while in C &#8216;Z&#8217;+1 turns into &#8216;[&#8216; ( ord(&#8216;Z&#8217;) == 90, ord(&#8216;[&#8216;) == 91 ). Note that character variables can be incremented but not decremented and even so only plain ASCII characters (a-z and A-Z) are supported.
</p></blockquote>
<p>     在处理字符变量的算数运算时，PHP 沿袭了 Perl 的习惯，而非 C 的。例如，在 Perl 中 &#8216;Z&#8217;+1 将得到 &#8216;AA&#8217;，而在 C 中，&#8217;Z'+1 将得到 &#8216;[&#8216;（ord(&#8216;Z&#8217;) == 90，ord(&#8216;[&#8216;) == 91）。注意字符变量只能递增，不能递减，并且只支持纯字母（a-z 和 A-Z）。</p>
<p>     也就是说, 如果:</p>
<pre name="code"  class="sh_php"  linenum="off"   style="background: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:Monacobackground: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:MonacoConsolasConsolasCourierCouriermonospace;monospace;">
$name = &quot;laruence&quot;;
++$name; //将会是&quot;laruencf&quot;
</pre>
<p>     而:</p>
<pre name="code"  class="sh_php"  linenum="off"   style="background: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:Monacobackground: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:MonacoConsolasConsolasCourierCouriermonospace;monospace;">
$name = &quot;laruence&quot;;
--$name; //没有影响, 还是&quot;laruence&quot;
</pre>
<p>    所以, 这个问题的原因就是当$i = Z的时候, ++$i成了AA, 而字符串比较的话,<br/>
AA,BB,XX一直到YZ都是小于等于Z的&#8230; so..</p>
<p>    最后, 说个题外话:  <a href="http://www.laruence.com" >Blog</a>现在支持订阅评论了, 同学们有提问以后等我回答的, 可以在留言提问的时候, 选择:Notify me of followup comments via e-mail<script type="text/javascript"  src="http://www.laruence.com/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_php.js" ></script><script type="text/javascript"  src="http://www.laruence.com/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_php.js" ></script><script type="text/javascript"  src="http://www.laruence.com/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_php.js" ></script></p>
<hr/><h2>Comments</h2><ul  style="padding-left:1em;font-size:85%;padding-left:1em;font-size:85%;"><li><a href="http://www.laruence.com/2010/07/30/1682.html#comment-3017" >2010/07/31</a>, <a href="http://www.phppan.com"  rel="external nofollow"  class="url" >胖子</a> writes: 学习了，感谢鸟哥</li><li><a href="http://www.laruence.com/2010/07/30/1682.html#comment-3018" >2010/07/31</a>, <a href="http://www.phppan.com"  rel="external nofollow"  class="url" >胖子</a> writes: 其实说明了另一个问题：PHP中没有字符，即使用chr,返回的也是一个长度为1的字符串
如：
var_dump(chr(90));
得到：
string 'Z' (length=1)</li><li><a href="http://www.laruence.com/2010/07/30/1682.html#comment-3020" >2010/07/31</a>, <a href="http://www.laruence.com"  rel="external nofollow"  class="url" >雪候鸟</a> writes: @胖子 这个总结挺Cool:"PHP中没有字符"</li><li><a href="http://www.laruence.com/2010/07/30/1682.html#comment-3022" >2010/07/31</a>, <a href="http://www.jaceju.net/blog/?p=1319"  rel="external nofollow"  class="url" >網站製作學習誌 &raquo; [Web] 連結分享</a> writes: [...] 注意PHP对字符串的递增运算 [...]</li><li><a href="http://www.laruence.com/2010/07/30/1682.html#comment-3024" >2010/08/01</a>, <a href="http://topsy.com/www.laruence.com/2010/07/30/1682.html?utm_source=pingback&amp;utm_campaign=L2"  rel="external nofollow"  class="url" >Tweets that mention 注意PHP对字符串的递增运算 | 风雪之隅 -- Topsy.com</a> writes: [...] This post was mentioned on Twitter by Angus Li, 小夜. 小夜 said: 注意PHP对字符串的递增运算 : http://goo.gl/0Koy [...]</li><li><a href="http://www.laruence.com/2010/07/30/1682.html#comment-3027" >2010/08/02</a>, <a href="http://blog.thinkinlamp.com/?p=373"  rel="external nofollow"  class="url" >Think In LAMP Blog &raquo; Blog Archive &raquo; PHP每周通讯（20100802）</a> writes: [...] 风雪之隅　　　　　　　注意PHP对字符串的递增运算  　　　　　　　　　　　http://www.laruence.com/2010/07/30/1682.html  [...]</li><li><a href="http://www.laruence.com/2010/07/30/1682.html#comment-3028" >2010/08/03</a>, <a href="http://www.bixuda.com/2010/08/03/%e8%bd%ac%e6%b3%a8%e6%84%8fphp%e5%af%b9%e5%ad%97%e7%ac%a6%e4%b8%b2%e7%9a%84%e9%80%92%e5%a2%9e%e8%bf%90%e7%ae%97/"  rel="external nofollow"  class="url" >[转]注意PHP对字符串的递增运算 | { yeah : 必须哒 }</a> writes: [...] 本文地址: http://www.laruence.com/2010/07/30/1682.html [...]</li><li><a href="http://www.laruence.com/2010/07/30/1682.html#comment-3030" >2010/08/03</a>, <a href="###"  rel="external nofollow"  class="url" >江湖游医</a> writes: 大师就是大师啊.
看来很平常的问题,经过一分析原来其中还有大道理..</li><li><a href="http://www.laruence.com/2010/07/30/1682.html#comment-3034" >2010/08/03</a>, <a href="http://hi.baidu.com/luk4u"  rel="external nofollow"  class="url" >luk4u</a> writes: 博主，您好，关注你的博客有一段时间了，感觉非常会钻研。我也有看php的c代码，memcached，nginx代码都有看过。我的博客http://hi.baidu.com/luk4u，希望多多指点我 ^^</li><li><a href="http://www.laruence.com/2010/07/30/1682.html#comment-3039" >2010/08/04</a>, <a href="http://www.laruence.com"  rel="external nofollow"  class="url" >雪候鸟</a> writes: @luk4u 你好, 指点不敢, 有问题可以互相交流, :)</li><li><a href="http://www.laruence.com/2010/07/30/1682.html#comment-3082" >2010/08/14</a>, <a href="http://roygu.com/?p=837"  rel="external nofollow"  class="url" >php字符递增问题 | Roy Gu</a> writes: [...] = &#39;A&#39;; $i  输出竟然是&#39;AA&#39;。。。这确实让人意外，最后在laruence的博客中找到了解释，原来当$i = [...]</li></ul><hr/><small  style="font-size:85%;font-size:85%;">Copyright &copy; 2010 <a href="http://www.laruence.com"  target="_blank" >风雪之隅</a> 版权所有, 转载务必注明. 该Feed只供个人使用, 禁止未注明的转载或商业应用. 非法应用的, 一切法律后果自负. 如有问题, 可发E-mail至my at laruence.com.(Digital Fingerprint: 73540ba0a1738d7d07d4b6038d5615e2)</small>]]></content:encoded>
			<wfw:commentRss>http://www.laruence.com/2010/07/30/1682.html/feed</wfw:commentRss>
		<slash:comments>11</slash:comments>
		</item>
		<item>
		<title>PHP运算符优先级的一个例外</title>
		<link>http://www.laruence.com/2010/07/26/1668.html</link>
		<comments>http://www.laruence.com/2010/07/26/1668.html#comments</comments>
		<pubDate>Mon, 26 Jul 2010 09:27:43 +0000</pubDate>
		<dc:creator>雪候鸟</dc:creator>
				<category><![CDATA[PHP应用]]></category>
		<category><![CDATA[PHP源码分析]]></category>
		<category><![CDATA[operator precedence]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[运算符优先级]]></category>

		<guid isPermaLink="false">http://www.laruence.com/?p=1668</guid>
		<description><![CDATA[今天在老王的技术手册看到一个问题:
<coolcode lang="php" linenum="off">
<?php
if ($a = 100 &#038;& $b = 200) {
	var_dump($a, $b);
}
</coolcode>
	
    输出是什么?

     这个问题, 咋一看或许觉得简单, 但其实仔细推敲并不简单.]]></description>
			<content:encoded><![CDATA[<div class="copyright" >
<ul  style="padding-left:1em;font-size:85%;padding-left:1em;font-size:85%;">
<li>作者: laruence(<a href="http://www.laruence.com"  title="风雪之隅"  target="_blank" >http://www.laruence.com</a>)</li>
<li>本文地址: <a href="http://www.laruence.com/2010/07/26/1668.html"  title="Permanet Link to PHP运算符优先级的一个例外" >http://www.laruence.com/2010/07/26/1668.html</a></li>
<li>转载请注明出处 </li>
</ul></div>
<p>
	今天在<a href="http://hi.baidu.com/thinkinginlamp/blog/item/5e8062d9b33ccc2110df9b2a.html"  target="_blank" >老王的技术手册</a>看到一个问题:</p>
<pre name="code"  class="sh_php"  linenum="off"   style="background: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:Monacobackground: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:MonacoConsolasConsolasCourierCouriermonospace;monospace;">
&lt;?php
if ($a = 100 &amp;&amp; $b = 200) {
	var_dump($a, $b);
}
</pre>
<p>    输出是什么?</p>
<p>    这个问题, 咋一看或许觉得简单, 但其实仔细推敲并不简单,</p>
<p>	如果说布尔与之前的部分, 是由于优先级的问题,  但是如果仅仅是优先级的问题的话, 那么结果应该是:</p>
<pre name="code"  class="sh_php"  linenum="off"   style="background: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:Monacobackground: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:MonacoConsolasConsolasCourierCouriermonospace;monospace;">
$a = (100 &amp;&amp; $b) = 200
</pre>
<p>	而实际上的结果, 确实高优先级的&#038;&#038;让步给次优先级的=, 让 $b = 200 先结合了. </p>
<p>	究其原因, 是因为PHP并不完全遵守优先级的定义, 这个在PHP的手册中也有说明:</p>
<blockquote><p>
Note: Although = has a lower precedence than most other operators, PHP will still allow expressions similar to the following: if (!$a = foo()), in which case the return value of foo() is put into $a.
</p></blockquote>
<p>	这样的设计, 个人不发表看法, 反正在C语言中, 这样类似的语句是判定为语法错的. PHP采用这样的设计, 很可能是历史原因, </p>
<p>	有好奇的同学, 会想知道到底为什么, 之前jayeeliu网友也问过:</p>
<blockquote><p>
laruence你好：<br/>
	问一个php运算符优先级的问题<br/>
		$t == 1 &#038;&#038; $tt = 2<br/>
	按照php运算符优先级应该是<br/>
		(($t == 1) &#038;&#038; $tt) = 2<br/>
	这个顺序执行，但实际上应该是<br/>
		($t == 1) &#038;&#038; ($tt = 2)<br/>
	我有些不太理解。
</p></blockquote>
<p>  	其实也简单, 运算符优先级是在存在二义性文法的时候的一种规约规则选择的手段,  而PHP的语法分析文件定义中, 却让等号和T_BOOLEAN_AND(&#038;&#038;)之前不存在了规约冲突:</p>
<pre name="code"  class="sh_bash"  linenum="off"   style="background: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:Monacobackground: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:MonacoConsolasConsolasCourierCouriermonospace;monospace;">
expr_without_variable:
  // 有隐规则存在, 相当于T_BOOLEAN_AND成为了&quot;一元操作符&quot;.
  |   expr T_BOOLEAN_AND  { zend_do_boolean_and_begin(&amp;$1, &amp;$2 TSRMLS_CC); } expr
</pre>
<p>      最后, 顺便说一下, PHP对应于T_BOOLEAN_AND 还定义了 T_LOGICAL_AND(and) 和 T_LOGICAL_OR(or) , 这俩个的优先级都低于等号, 于是就会有了, 很多PHP入门教材示例代码中经典的:</p>
<pre name="code"  class="sh_php"  linenum="off"   style="background: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:Monacobackground: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:MonacoConsolasConsolasCourierCouriermonospace;monospace;">
$result = mysql_query(*)  or die(mysql_error());
</pre>
<p>	类似的还可以用or来实现三元操作符(?:)的功能:</p>
<pre name="code"  class="sh_php"  linenum="off"   style="background: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:Monacobackground: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:MonacoConsolasConsolasCourierCouriermonospace;monospace;">
	$person = $who or $person = &quot;laruence&quot;;
//等同于:
	$person = empty($who)? &quot;laruence&quot; : $who;
</pre>
<p><script type="text/javascript"  src="http://www.laruence.com/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_php.js" ></script><script type="text/javascript"  src="http://www.laruence.com/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_php.js" ></script><script type="text/javascript"  src="http://www.laruence.com/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_bash.js" ></script><script type="text/javascript"  src="http://www.laruence.com/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_php.js" ></script><script type="text/javascript"  src="http://www.laruence.com/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_php.js" ></script></p>
<hr/><h2>Comments</h2><ul  style="padding-left:1em;font-size:85%;padding-left:1em;font-size:85%;"><li><a href="http://www.laruence.com/2010/07/26/1668.html#comment-2988" >2010/07/26</a>, <a href="http://www.blogismoney.net"  rel="external nofollow"  class="url" >半醒</a> writes: mysql connect那语句的确很经典

这种优先级的约束能不能认为是更符合人的自然思维？</li><li><a href="http://www.laruence.com/2010/07/26/1668.html#comment-2989" >2010/07/26</a>, <a href="http://t.sina.com.cn/liruqi"  rel="external nofollow"  class="url" >liruqi</a> writes: 这种问题挺tricky
还是尽量避免magic code比较方便。</li><li><a href="http://www.laruence.com/2010/07/26/1668.html#comment-2990" >2010/07/26</a>, <a href="http://test"  rel="external nofollow"  class="url" >yyj</a> writes: 

alert('ddd');
</li><li><a href="http://www.laruence.com/2010/07/26/1668.html#comment-2991" >2010/07/26</a>, <a href="http://www.laruence.com"  rel="external nofollow"  class="url" >雪候鸟</a> writes: @yyj 你想xss我? 太坏了..</li><li><a href="http://www.laruence.com/2010/07/26/1668.html#comment-2994" >2010/07/27</a>, anyharding writes: 为什么要写歧义代码，加上小括号不就好了吗？
代码是让人读的，提高可读性的同时，也避免犯一些错误</li><li><a href="http://www.laruence.com/2010/07/26/1668.html#comment-2995" >2010/07/27</a>, <a href="http://www.jingying.org.cn/"  rel="external nofollow"  class="url" >火跃</a> writes: 不错！学习了！</li><li><a href="http://www.laruence.com/2010/07/26/1668.html#comment-2998" >2010/07/27</a>, <a href="http://www.laruence.com"  rel="external nofollow"  class="url" >雪候鸟</a> writes: @anyharding 我们可以要求自己的代码易读, 但无法保证别人的代码. :)</li><li><a href="http://www.laruence.com/2010/07/26/1668.html#comment-3019" >2010/07/31</a>, <a href="http://www.yeeger.com/?p=144"  rel="external nofollow"  class="url" >PHP运算符的两个问题 | yeeger.com</a> writes: [...] 本文地址: http://www.laruence.com/2010/07/26/1668.html [...]</li><li><a href="http://www.laruence.com/2010/07/26/1668.html#comment-3021" >2010/07/31</a>, <a href="http://www.jaceju.net/blog/?p=1319"  rel="external nofollow"  class="url" >網站製作學習誌 &raquo; [Web] 連結分享</a> writes: [...] PHP运算符优先级的一个例外 [...]</li><li><a href="http://www.laruence.com/2010/07/26/1668.html#comment-3023" >2010/07/31</a>, <a href="http://www.paitoubing.cn"  rel="external nofollow"  class="url" >排头兵</a> writes: 受教，呵呵。

优先级 ！！！</li><li><a href="http://www.laruence.com/2010/07/26/1668.html#comment-3026" >2010/08/02</a>, <a href="http://blog.thinkinlamp.com/?p=373"  rel="external nofollow"  class="url" >Think In LAMP Blog &raquo; Blog Archive &raquo; PHP每周通讯（20100802）</a> writes: [...] 风雪之隅　　　　　　　PHP运算符优先级的一个例外  　　　　　　　　　　　http://www.laruence.com/2010/07/26/1668.html  [...]</li><li><a href="http://www.laruence.com/2010/07/26/1668.html#comment-3099" >2010/08/21</a>, <a href="http://www.coderbolg.com"  rel="external nofollow"  class="url" >蓝色夏威夷</a> writes: 额，有意思啊。</li><li><a href="http://www.laruence.com/2010/07/26/1668.html#comment-3125" >2010/08/31</a>, <a href="http://www.166ck.com"  rel="external nofollow"  class="url" >Audio</a> writes: 以前还一直没遇到过这种情况，受教了！以后写代码还是要多按标准写！</li></ul><hr/><small  style="font-size:85%;font-size:85%;">Copyright &copy; 2010 <a href="http://www.laruence.com"  target="_blank" >风雪之隅</a> 版权所有, 转载务必注明. 该Feed只供个人使用, 禁止未注明的转载或商业应用. 非法应用的, 一切法律后果自负. 如有问题, 可发E-mail至my at laruence.com.(Digital Fingerprint: 73540ba0a1738d7d07d4b6038d5615e2)</small>]]></content:encoded>
			<wfw:commentRss>http://www.laruence.com/2010/07/26/1668.html/feed</wfw:commentRss>
		<slash:comments>13</slash:comments>
		</item>
		<item>
		<title>终于搞定了IE6下的显示</title>
		<link>http://www.laruence.com/2010/07/23/1664.html</link>
		<comments>http://www.laruence.com/2010/07/23/1664.html#comments</comments>
		<pubDate>Fri, 23 Jul 2010 07:31:06 +0000</pubDate>
		<dc:creator>雪候鸟</dc:creator>
				<category><![CDATA[随笔]]></category>

		<guid isPermaLink="false">http://www.laruence.com/?p=1664</guid>
		<description><![CDATA[<p>
   之前就有博友跟我说, 我的blog在IE6下页面乱了.

   一直懒得弄, 今天有点时间, 打算调整下.

   找了半天, 罪魁祸首原来是我给pre设置的左边框, 具体原因我还不知道.. 有知道同学, 指点我一下... hack以后,,就好了:
<coolcode lang="html" linenum="off">
pre {
 border-left: 15px corlor solid; 
_border-left:none; //可恶的IE6
}
</coolcode>
   
    每当这个时候, 我就会忠心的感谢发现这些css Hack的先驱们....]]></description>
			<content:encoded><![CDATA[<div class="copyright" >
<ul  style="padding-left:1em;font-size:85%;padding-left:1em;font-size:85%;">
<li>作者: laruence(<a href="http://www.laruence.com"  title="风雪之隅"  target="_blank" >http://www.laruence.com</a>)</li>
<li>本文地址: <a href="http://www.laruence.com/2010/07/23/1664.html"  title="Permanet Link to 终于搞定了IE6下的显示" >http://www.laruence.com/2010/07/23/1664.html</a></li>
<li>转载请注明出处 </li>
</ul></div>
<p>
   之前就有博友跟我说, 我的blog在IE6下页面乱了.</p>
<p>   一直懒得弄, 今天有点时间, 打算调整下.</p>
<p>   找了半天, 罪魁祸首原来是我给pre设置的左边框, 具体原因我还不知道.. 有知道同学, 指点我一下&#8230; hack以后,,就好了:</p>
<pre name="code"  class="sh_html"  linenum="off"   style="background: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:Monacobackground: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:MonacoConsolasConsolasCourierCouriermonospace;monospace;">
pre {
 border-left: 15px corlor solid;
_border-left:none; //可恶的IE6
}
</pre>
<p>    每当这个时候, 我就会忠心的感谢发现这些css Hack的先驱们&#8230;.<script type="text/javascript"  src="http://www.laruence.com/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_html.js" ></script></p>
<hr/><h2>Comments</h2><ul  style="padding-left:1em;font-size:85%;padding-left:1em;font-size:85%;"><li><a href="http://www.laruence.com/2010/07/23/1664.html#comment-2978" >2010/07/25</a>, <a href="http://www.cnxct.com"  rel="external nofollow"  class="url" >CFC4N</a> writes: 鸟哥还精通CSS，膜拜。
验证码：Dan</li><li><a href="http://www.laruence.com/2010/07/23/1664.html#comment-2986" >2010/07/26</a>, <a href="http://www.taobaowenda.com"  rel="external nofollow"  class="url" >淘宝问答</a> writes: <a href="http://www.taobaowenda.com/"  rel="nofollow" >淘宝问答</a>膜拜。</li><li><a href="http://www.laruence.com/2010/07/23/1664.html#comment-3102" >2010/08/22</a>, <a href="http://www.klwangzi.cn/"  rel="external nofollow"  class="url" >最有效的减肥产品</a> writes: 最近有个网站一直有排版错位的问题，很是头疼。听朋友说是分辨率问题，但在IE6以上的其他浏览器都显示正常。搞的很郁闷。网站是表格做的。。</li><li><a href="http://www.laruence.com/2010/07/23/1664.html#comment-3126" >2010/08/31</a>, <a href="http://www.jyttv.com/"  rel="external nofollow"  class="url" >久益视界</a> writes: CSS前段时间学习了下，不过还是不能布局，嘿嘿</li></ul><hr/><small  style="font-size:85%;font-size:85%;">Copyright &copy; 2010 <a href="http://www.laruence.com"  target="_blank" >风雪之隅</a> 版权所有, 转载务必注明. 该Feed只供个人使用, 禁止未注明的转载或商业应用. 非法应用的, 一切法律后果自负. 如有问题, 可发E-mail至my at laruence.com.(Digital Fingerprint: 73540ba0a1738d7d07d4b6038d5615e2)</small>]]></content:encoded>
			<wfw:commentRss>http://www.laruence.com/2010/07/23/1664.html/feed</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>定制自己的PHP语法-在PHP中实现unless</title>
		<link>http://www.laruence.com/2010/07/16/1648.html</link>
		<comments>http://www.laruence.com/2010/07/16/1648.html#comments</comments>
		<pubDate>Fri, 16 Jul 2010 10:07:35 +0000</pubDate>
		<dc:creator>雪候鸟</dc:creator>
				<category><![CDATA[PHP应用]]></category>
		<category><![CDATA[PHP源码分析]]></category>

		<guid isPermaLink="false">http://www.laruence.com/?p=1648</guid>
		<description><![CDATA[	今天有人问我, 说他看到有PHPer在说unless语句, 我很是纳闷, 后来才知道, 原来是一个国外的PHP大牛自己Hack了PHP的源码, 加入了一个unless语句.
    
        很有意思, 今天, 我也就在这里为大家演示, 如何为我们自己的PHP加入unless语句..]]></description>
			<content:encoded><![CDATA[<div class="copyright" >
<ul  style="padding-left:1em;font-size:85%;padding-left:1em;font-size:85%;">
<li>作者: laruence(<a href="http://www.laruence.com"  title="风雪之隅"  target="_blank" >http://www.laruence.com</a>)</li>
<li>本文地址: <a href="http://www.laruence.com/2010/07/16/1648.html"  title="Permanet Link to 定制自己的PHP语法-在PHP中实现unless" >http://www.laruence.com/2010/07/16/1648.html</a></li>
<li>转载请注明出处 </li>
</ul></div>
<p>
	首先 ,插一句题外话:  从我发表第一篇PHP执行原理的文章到现在, 已经快2年了, 我很高兴的看到这俩年里PHP中文圈里 ,越来越多的人开始研究PHP源码, 也有越来越多的人开始从事PHP扩展开发.</p>
<p>    关于PHP的执行原理, 我想我BLOG的读者都能脱口而出:</p>
<pre name="code"  class="sh_php"  linenum="off"   style="background: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:Monacobackground: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:MonacoConsolasConsolasCourierCouriermonospace;monospace;">
1. 词法分析, 去掉注释, 空白, 得到TOKEN
2. 语法分析, 在这个过程中生成Opcode array (op_array)
3. 解释执行, 执行op_array, 一条一条的解释执行Opline(SWITCH, CALL, GOTO)
</pre>
<p>	今天有人问我, 说他看到有PHPer在说unless语句, 我很是纳闷, 后来才知道, 原来是一个国外的PHP大牛自己Hack了PHP的源码, 加入了一个unless语句.</p>
<p>        很有意思, 今天, 我也就在这里为大家演示, 如何为我们自己的PHP加入unless语句..</p>
<p>	如果你是不了解PHP的执行过程, 请先花点时间看看我之前的文章<a href="http://www.laruence.com/2008/06/18/221.html" >深入理解PHP原理之Opcodes</a>:</p>
<p>	我们的目标, 是要实现如下的语法(以php 5.2.11为基础):</p>
<pre name="code"  class="sh_php"  linenum="off"   style="background: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:Monacobackground: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:MonacoConsolasConsolasCourierCouriermonospace;monospace;">
&lt;?php
unless(TRUE) {
//这不会被执行
}
unless(FALSE) {
//这会被执行
}
</pre>
<p>	好得, 看起来unless是if的反义词了.. 那么就好办了, if怎么来, 我们相反的来就可以了..</p>
<p>    首先, 词法分析阶段, 我们需要添加unless的TOKEN定义, 编辑Zend/zend_language_scanner.l:</p>
<pre name="code"  class="sh_c"  linenum="off"   style="background: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:Monacobackground: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:MonacoConsolasConsolasCourierCouriermonospace;monospace;">
//添加unless的Token定义
&lt;ST_IN_SCRIPTING&gt;&quot;unless&quot; {
    return T_UNLESS;
}

&lt;ST_IN_SCRIPTING&gt;&quot;if&quot; {
    return T_IF;
}

&lt;ST_IN_SCRIPTING&gt;&quot;elseif&quot; {
    return T_ELSEIF;
}
</pre>
<p>	这样, 词法分析器遇到unless的时候, 就会报告发现了一个T_UNLESS Token.</p>
<p>	接下来就需要在语法分析阶段, 定义T_UNLESS的语法动作了, 编辑Zend/zend_language_parse.y</p>
<pre name="code"  class="sh_c"  linenum="off"   style="background: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:Monacobackground: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:MonacoConsolasConsolasCourierCouriermonospace;monospace;">
unticked_statement:
        '{' inner_statement_list '}'
    |   T_IF '(' expr ')' { zend_do_if_cond(&amp;$3, &amp;$4 TSRMLS_CC); }
		statement { zend_do_if_after_statement(&amp;$4, 1 TSRMLS_CC); }
		elseif_list else_single { zend_do_if_end(TSRMLS_C); }
//添加T_UNLESS的语法动作
	|   T_UNLESS '(' expr ')' { zend_do_unless_cond(&amp;$3, &amp;$4 TSRMLS_CC);}
		statement {zend_do_if_after_statement(&amp;$4, 1 TSRMLS_CC);}
				  {zend_do_if_end(TSRMLS_C)};
</pre>
<p>	对的, 因为if和unless只是在条件的真假上不同,  所以我在if的基础上, 做了这个简单的hack, 接下来, 就应该定义zend_do_unless_cond了, 这个逻辑是用来生成OPCODE的. 还是从zend_do_if_cond为基础来做修改, Zend/zend_compile.c:</p>
<pre name="code"  class="sh_c"  linenum="off"   style="background: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:Monacobackground: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:MonacoConsolasConsolasCourierCouriermonospace;monospace;">
void zend_do_if_cond(znode *cond, znode *closing_bracket_token TSRMLS_DC)
{
    int if_cond_op_number = get_next_op_number(CG(active_op_array));
    zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC); 

    opline-&gt;opcode = ZEND_JMPZ;  //如果为0则跳转
    opline-&gt;op1 = *cond;
    closing_bracket_token-&gt;u.opline_num = if_cond_op_number; //跳转地址
    SET_UNUSED(opline-&gt;op2);
    INC_BPC(CG(active_op_array));
}
</pre>
<p>	OK, 那么我们的zend_do_unless_cond就可以这样定义:</p>
<pre name="code"  class="sh_c"  linenum="off"   style="background: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:Monacobackground: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:MonacoConsolasConsolasCourierCouriermonospace;monospace;">
void zend_do_unless_cond(znode *cond, znode *closing_bracket_token TSRMLS_DC)
{
    int if_cond_op_number = get_next_op_number(CG(active_op_array));
    zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC); 

    opline-&gt;opcode = ZEND_JMPNZ;  //如果为不为0则跳转
    opline-&gt;op1 = *cond;
    closing_bracket_token-&gt;u.opline_num = if_cond_op_number;
    SET_UNUSED(opline-&gt;op2);
    INC_BPC(CG(active_op_array));
}
</pre>
<p>	注意上面的OPCODE, 我们把ZEND_JMPZ变成了JMPNZ&#8230;</p>
<p>    大功告成, 现在需要重新编译PHP了:</p>
<pre name="code"  class="sh_bash"  linenum="off"   style="background: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:Monacobackground: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:MonacoConsolasConsolasCourierCouriermonospace;monospace;">
cd Zend;
rm zend_language_*.c;
cd phpsrc_dir;
make
</pre>
<p>	编写测试脚本:</p>
<pre name="code"  class="sh_php"  linenum="off"   style="background: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:Monacobackground: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:MonacoConsolasConsolasCourierCouriermonospace;monospace;">
&lt;?php
unless(FALSE) {
    echo &quot;Laruence&quot;;
}
</pre>
<p>	运行&#8230;..</p>
<p>       最后,  举的这个例子,相对来说是简单的, 因为有if可以参照,  有兴趣的同学, 可以自己玩玩, 用PHP实现其它语言中的各种语法~~<script type="text/javascript"  src="http://www.laruence.com/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_php.js" ></script><script type="text/javascript"  src="http://www.laruence.com/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_php.js" ></script><script type="text/javascript"  src="http://www.laruence.com/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_c.js" ></script><script type="text/javascript"  src="http://www.laruence.com/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_c.js" ></script><script type="text/javascript"  src="http://www.laruence.com/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_c.js" ></script><script type="text/javascript"  src="http://www.laruence.com/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_c.js" ></script><script type="text/javascript"  src="http://www.laruence.com/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_bash.js" ></script><script type="text/javascript"  src="http://www.laruence.com/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_php.js" ></script></p>
<hr/><h2>Comments</h2><ul  style="padding-left:1em;font-size:85%;padding-left:1em;font-size:85%;"><li><a href="http://www.laruence.com/2010/07/16/1648.html#comment-2954" >2010/07/16</a>, <a href="http://skiyo.cn"  rel="external nofollow"  class="url" >Skiyo</a> writes: 鸟哥玩PHP已经炉火纯青了 这个想法超赞的。。

我们可以定制一个自己的开源PHP。。</li><li><a href="http://www.laruence.com/2010/07/16/1648.html#comment-2955" >2010/07/16</a>, <a href="http://www.zendstudio.net/"  rel="external nofollow"  class="url" >gently</a> writes: 鸟哥的思路太令人称道了。好文！</li><li><a href="http://www.laruence.com/2010/07/16/1648.html#comment-2957" >2010/07/16</a>, <a href="http://topsy.com/www.laruence.com/2010/07/16/1648.html?utm_source=pingback&amp;utm_campaign=L2"  rel="external nofollow"  class="url" >Tweets that mention 定制自己的PHP语法-在PHP中实现unless | 风雪之隅 -- Topsy.com</a> writes: [...] This post was mentioned on Twitter by 心跳失忆, Laruence. Laruence said: 定制自己的 PHP语法-在PHP中实现unless http://www.laruence.com/2010/07/16/1648.html [...]</li><li><a href="http://www.laruence.com/2010/07/16/1648.html#comment-2958" >2010/07/16</a>, Amaranth writes: 基本上php源码分析里的文章我都看不懂..咋整..</li><li><a href="http://www.laruence.com/2010/07/16/1648.html#comment-2959" >2010/07/17</a>, <a href="http://www.phppan.com"  rel="external nofollow"  class="url" >胖子</a> writes: 过来跟鸟哥学习</li><li><a href="http://www.laruence.com/2010/07/16/1648.html#comment-2963" >2010/07/18</a>, <a href="http://www.js4j.com/"  rel="external nofollow"  class="url" >技术论坛</a> writes: 超赞</li><li><a href="http://www.laruence.com/2010/07/16/1648.html#comment-2982" >2010/07/26</a>, <a href="http://blog.thinkinlamp.com/?p=324"  rel="external nofollow"  class="url" >Think In LAMP Blog &raquo; Blog Archive &raquo; PHP每周通讯（20100726）</a> writes: [...] 风雪之隅：《定制自己的PHP语法-在PHP中实现unless》 [...]</li><li><a href="http://www.laruence.com/2010/07/16/1648.html#comment-2996" >2010/07/27</a>, Risun writes: 过来学习，离你的境界还太远啊，努力中</li></ul><hr/><small  style="font-size:85%;font-size:85%;">Copyright &copy; 2010 <a href="http://www.laruence.com"  target="_blank" >风雪之隅</a> 版权所有, 转载务必注明. 该Feed只供个人使用, 禁止未注明的转载或商业应用. 非法应用的, 一切法律后果自负. 如有问题, 可发E-mail至my at laruence.com.(Digital Fingerprint: 73540ba0a1738d7d07d4b6038d5615e2)</small>]]></content:encoded>
			<wfw:commentRss>http://www.laruence.com/2010/07/16/1648.html/feed</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
		<item>
		<title>Facebook发布又一PHP改进项目XHP</title>
		<link>http://www.laruence.com/2010/07/16/1638.html</link>
		<comments>http://www.laruence.com/2010/07/16/1638.html#comments</comments>
		<pubDate>Fri, 16 Jul 2010 07:14:27 +0000</pubDate>
		<dc:creator>雪候鸟</dc:creator>
				<category><![CDATA[PHP应用]]></category>
		<category><![CDATA[转载]]></category>

		<guid isPermaLink="false">http://www.laruence.com/?p=1638</guid>
		<description><![CDATA[   根据Github上项目的文档维基，XHP是一个PHP扩展，通过它，开发人员可以直接在PHP代码中内嵌XML文档片段，作为合法的PHP表达式。这样，PHP就成为一个更为严格的模板引擎，大大简化了实现可重用组件的工作。
]]></description>
			<content:encoded><![CDATA[<div class="copyright" >
<ul  style="padding-left:1em;font-size:85%;padding-left:1em;font-size:85%;">
<li>本文地址: <a href="http://www.laruence.com/2010/07/16/1638.html"  title="Permanet Link to Facebook发布又一PHP改进项目XHP" >http://www.laruence.com/2010/07/16/1638.html</a></li>
<li>文章转自: http://news.csdn.net/a/20100211/216991.html</li>
</ul></div>
<p>     就在Google高调发布业界普遍认为针对Facebook的Buzz的同时，Facebook则低调发布了XHP项目。这是一个多月以来，继HipHop之后，Facebook推出的又一重要PHP改进项目。看来，在社会化网络市场地位稳固之后，Facebook也开始大力回馈技术社区，在口碑和攒人品方面与Google展开竞争了。</p>
<p>   根据<a href="http://wiki.github.com/facebook/xhp/"  target="_blank" >Github上项目的文档维基</a>，XHP是一个PHP扩展，通过它，开发人员可以直接在PHP代码中内嵌XML文档片段，作为合法的PHP表达式。这样，PHP就成为一个更为严格的模板引擎，大大简化了实现可重用组件的工作。</p>
<p>比如这样的简单代码示例：</p>
<pre name="code"  class="sh_php"  linenum="off"   style="background: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:Monacobackground: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:MonacoConsolasConsolasCourierCouriermonospace;monospace;">
&lt;?php
rquire &quot;xphsrc/php-lib/init.php&quot;;
$href = 'http://www.facebook.com';
echo &lt;a href={$href}&gt;Facebook&lt;/a&gt;
</pre>
<p>注意第三行代码中的语法，其中echo后的不是字符串。</p>
<p>项目负责人Facebook工程师Marcel Laverdet则表示，XHP不仅使前端代码更容易理解，还有助于防止跨站脚本攻击。事实上，Facebook Lite网站（快速简化版本的Facebook）就是完全用XHP写成的。</p>
<p>和上次HipHop发布一样，PHP之父Rasmus Lerdorf也很快做出回应（<a href="http://toys.lerdorf.com/archives/54-A-quick-look-at-XHP.html" >英文原文链接</a>），他说：</p>
<blockquote><p>XHP其实就是支持内嵌XML，这在VB中称为<a href="http://msdn.microsoft.com/zh-cn/library/bb384832.aspx" >XML元素文本</a>。它增加了一个额外的分析步骤，将内嵌的XML元素映射为PHP类。类的语法有些奇怪。至少对我而言，其中主要有意思的地方，是PHP现在理解要输出的XML了，就可以以上下文敏感的方式进行过滤。</p></blockquote>
<p>Lerdorf也指出，XHP存在明显的性能问题，它的XML运行时验证显然会增加开销。为此，Facebook不得不使用APC[Alternative PHP Cache]再加上HipHop。</p>
<p>对此，Marcel Laverdet回复：</p>
<blockquote><p>性能的确是XHP最引人关注的问题。确实，XHP比原始的字符串拼接要慢2到3倍，但是这对大多数程序都不是问题。另外，虽然APC肯定是必需的（大多数网站都是如此），HipHop则不然。其实Lite网站只是到最近才开始切换到HipHop，之前也表现很不错。在实际应用中，XHP对性能影响并不是很大。在简洁和性能之间的权衡上，XHP做得不错。</p></blockquote>
<p>此外，Wikispaces的创始人James Byers也写到：</p>
<blockquote><p>对我来说，XHP比HipHop有意思得多。它将完全改变模板还是只用PHP的争论。对此我很高兴。PHP应该继续这样改进。</p></blockquote>
<p>Tipjoy的联合创始人，现在也在Facebook任工程师的Ivan Kirigin也对XHP赞赏有加：</p>
<blockquote><p>XHP是我在Facebook唯一使用的PHP工具，比其他语言类似的东西都好。记号完美代表了对象，不用折腾面向对象编程那些烂东西了，这可是非常罕见的宝贝。</p></blockquote>
<p><script type="text/javascript"  src="http://www.laruence.com/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_php.js" ></script></p>
<hr/><h2>Comments</h2><ul  style="padding-left:1em;font-size:85%;padding-left:1em;font-size:85%;"><li><a href="http://www.laruence.com/2010/07/16/1638.html#comment-2945" >2010/07/16</a>, <a href="http://liruqi.cn/"  rel="external nofollow"  class="url" >liruqi</a> writes: 赞, 这东西可以直接替代smarty框架了.</li><li><a href="http://www.laruence.com/2010/07/16/1638.html#comment-2946" >2010/07/16</a>, <a href="http://dothing"  rel="external nofollow"  class="url" >lake</a> writes: 又有得折腾了，也证明了php持续在受到关注。</li><li><a href="http://www.laruence.com/2010/07/16/1638.html#comment-2951" >2010/07/16</a>, <a href="http://www.bpzc.net/"  rel="external nofollow"  class="url" >bpzc</a> writes: 热切关注中~~~</li><li><a href="http://www.laruence.com/2010/07/16/1638.html#comment-2956" >2010/07/16</a>, <a href="http://www.laruence.com"  rel="external nofollow"  class="url" >雪候鸟</a> writes: @liruqi 还能做标签配对检查, 输出转义,,,,,</li><li><a href="http://www.laruence.com/2010/07/16/1638.html#comment-2961" >2010/07/17</a>, <a href="http://topsy.com/www.laruence.com/2010/07/16/1638.html?utm_source=pingback&amp;utm_campaign=L2"  rel="external nofollow"  class="url" >Tweets that mention Facebook发布又一PHP改进项目XHP | 风雪之隅 -- Topsy.com</a> writes: [...] This post was mentioned on Twitter by 大房 and Jason Yu, Angus Li. Angus Li said: Facebook发布又一PHP改进项目XHP http://ff.im/-nNZx8 [...]</li><li><a href="http://www.laruence.com/2010/07/16/1638.html#comment-2962" >2010/07/17</a>, <a href="http://woshimaijia.com"  rel="external nofollow"  class="url" >xinqiyang</a> writes: 这样有个好处就是落花了模板引擎的了.......

关注下呵呵</li><li><a href="http://www.laruence.com/2010/07/16/1638.html#comment-2969" >2010/07/22</a>, <a href="http://www.xiuyu.com"  rel="external nofollow"  class="url" >修愚</a> writes: 路过，学习</li><li><a href="http://www.laruence.com/2010/07/16/1638.html#comment-2981" >2010/07/26</a>, wclssdn writes: 我怎么感觉模板框架是为了分工而使用的呢- - 

美工直接修改模板文件而不必理会PHP代码.. 

要是按照上边所说的... 内个. php程序员无敌了..</li><li><a href="http://www.laruence.com/2010/07/16/1638.html#comment-3133" >2010/09/01</a>, <a href="http://www.globalmarket.com"  rel="external nofollow"  class="url" >China Suppliers</a> writes: PHP被应用得越来越广泛了。以前我只看到了大多数人开始倾向用PHP来做网站，现在SNS的应用也开始使用PHP了。</li></ul><hr/><small  style="font-size:85%;font-size:85%;">Copyright &copy; 2010 <a href="http://www.laruence.com"  target="_blank" >风雪之隅</a> 版权所有, 转载务必注明. 该Feed只供个人使用, 禁止未注明的转载或商业应用. 非法应用的, 一切法律后果自负. 如有问题, 可发E-mail至my at laruence.com.(Digital Fingerprint: 73540ba0a1738d7d07d4b6038d5615e2)</small>]]></content:encoded>
			<wfw:commentRss>http://www.laruence.com/2010/07/16/1638.html/feed</wfw:commentRss>
		<slash:comments>9</slash:comments>
		</item>
		<item>
		<title>ReflectionFunction(Method)引用参数导致Invocation failed</title>
		<link>http://www.laruence.com/2010/06/22/1618.html</link>
		<comments>http://www.laruence.com/2010/06/22/1618.html#comments</comments>
		<pubDate>Tue, 22 Jun 2010 07:18:37 +0000</pubDate>
		<dc:creator>雪候鸟</dc:creator>
				<category><![CDATA[PHP应用]]></category>
		<category><![CDATA[PHP源码分析]]></category>
		<category><![CDATA[Invocation failed]]></category>
		<category><![CDATA[RefelctionMethod]]></category>
		<category><![CDATA[ReflectionFunction]]></category>

		<guid isPermaLink="false">http://www.laruence.com/?p=1618</guid>
		<description><![CDATA[ 今天同事反馈一个问题, PHP5.2.x在使用反射做函数包装的时候, 得到"Invocation failed"的异常, 而使用call_user_func代替则不会, 

  原逻辑太复杂, 经过精简以后可重现异常的代码如下(使用ReflectionFunction为例, ReflectionMethod类似):
<coolcode lang="php" linenum="off">
function who(&#038;$name) {
    echo $name;
}
$name = "laruence";
$method = new ReflectionFunction("who");
$method->invokeArgs(array($name));
//异常:
Uncaught exception 'ReflectionException' with message
'Invocation of function who() failed'                  
</coolcode>]]></description>
			<content:encoded><![CDATA[<div class="copyright" >
<ul  style="padding-left:1em;font-size:85%;padding-left:1em;font-size:85%;">
<li>作者: laruence(<a href="http://www.laruence.com"  title="风雪之隅"  target="_blank" >http://www.laruence.com</a>)</li>
<li>本文地址: <a href="http://www.laruence.com/2010/06/22/1618.html"  title="Permanet Link to ReflectionFunction(Method)引用参数导致Invocation failed" >http://www.laruence.com/2010/06/22/1618.html</a></li>
<li>转载请注明出处 </li>
</ul></div>
<p>
  今天同事反馈一个问题, PHP5.2.x在使用反射做函数包装的时候, 得到&#8221;Invocation failed&#8221;的异常, 而使用call_user_func代替则不会, </p>
<p>  原逻辑太复杂, 经过精简以后可重现异常的代码如下(使用ReflectionFunction为例, ReflectionMethod类似):</p>
<pre name="code"  class="sh_php"  linenum="off"   style="background: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:Monacobackground: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:MonacoConsolasConsolasCourierCouriermonospace;monospace;">
function who(&amp;$name) {
    echo $name;
}
$name = &quot;laruence&quot;;
$method = new ReflectionFunction(&quot;who&quot;);
$method-&gt;invokeArgs(array($name));
//异常:
Uncaught exception 'ReflectionException' with message
'Invocation of function who() failed'
</pre>
<p>  找原因过程中歧途我就不多言了,  最后跟踪到invokeArgs会调用Zend引擎提供的zend_call_function, 而在zend_call_function中, 有如下一段逻辑引起我的怀疑(注意注释部分):</p>
<pre name="code"  class="sh_c"  linenum="off"   style="background: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:Monacobackground: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:MonacoConsolasConsolasCourierCouriermonospace;monospace;">
int zend_call_function(zend_fcall_info *fci
         , zend_fcall_info_cache *fci_cache TSRMLS_DC) {
//以上省略
        if (ARG_SHOULD_BE_SENT_BY_REF(EX(function_state).function, i+1)
         &amp;&amp; !PZVAL_IS_REF(*fci-&gt;params[i])) {
/*如果形参是引用传递 并且参数不是引用 */
            if ((*fci-&gt;params[i])-&gt;refcount&gt;1) {
/*如果参数的refcount大于1 */
                zval *new_zval;

                if (fci-&gt;no_separation) {
/*如果不容许执行分离操作, 则返回失败 */
                    return FAILURE;
                }
//以下省略
</pre>
<p>  也就是说, 如果一个申明为引用传递的参数不为引用传递, 而refcount又大于1, 那么在不容许分离的条件下, 就会导致zend_call_function失败返回(如果对refcount和变量分离不了解, 可以参看我之前的文章<a href="http://www.laruence.com/2008/09/19/520.html" >深入理解PHP原理之变量分离/引用</a>).</p>
<p>  经过验证, 果然invokeArgs在构造zend_fcall_info fci的时候, 是禁止separation的, 所以导致zend_call_funcion返回FAILURE.</p>
<p>  而使用call_user_func则不会是因为,call_user_function不考虑no_separation直接分离, 这一点在PHP手册中, call_user_func中是有说明的:</p>
<pre name="code"  class="sh_bash"  linenum="off"   style="background: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:Monacobackground: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:MonacoConsolasConsolasCourierCouriermonospace;monospace;">
Note: Note that the parameters for call_user_func() are not passed by reference.
</pre>
<p>  找到了原因, 那解决的办法, 也就容易了:</p>
<pre name="code"  class="sh_php"  linenum="off"   style="background: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:Monacobackground: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:MonacoConsolasConsolasCourierCouriermonospace;monospace;">
function who(&amp;$name) {
    echo $name;
}
$name = &quot;laruence&quot;;
$method = new ReflectionFunction(&quot;who&quot;);
$method-&gt;invokeArgs(array(&amp;$name)); //is_ref
</pre>
<p><script type="text/javascript"  src="http://www.laruence.com/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_php.js" ></script><script type="text/javascript"  src="http://www.laruence.com/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_c.js" ></script><script type="text/javascript"  src="http://www.laruence.com/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_bash.js" ></script><script type="text/javascript"  src="http://www.laruence.com/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_php.js" ></script></p>
<hr/><h2>Comments</h2><ul  style="padding-left:1em;font-size:85%;padding-left:1em;font-size:85%;"><li><a href="http://www.laruence.com/2010/06/22/1618.html#comment-2830" >2010/06/22</a>, <a href="http://www.cnxct.com"  rel="external nofollow"  class="url" >CFC4N</a> writes: 鸟哥最近很高产，又出新作了。先占位，慢慢拜读。</li><li><a href="http://www.laruence.com/2010/06/22/1618.html#comment-2833" >2010/06/23</a>, <a href="http://www.sexynightwear.co.cc/"  rel="external nofollow"  class="url" >sexy nightwear</a> writes: Shop for <a href="http://www.sexynightwear.co.cc/"  rel="nofollow" >sexy nightwear</a>,satin nightwear,thongs,tights,stockings,chemises,nightgowns, corsets, costumes FREE UK delivery on all orders.</li><li><a href="http://www.laruence.com/2010/06/22/1618.html#comment-2841" >2010/06/24</a>, <a href="http://315.eduxuexi.com"  rel="external nofollow"  class="url" >打假网</a> writes: word shown in the picture. Click on t</li><li><a href="http://www.laruence.com/2010/06/22/1618.html#comment-2849" >2010/06/26</a>, <a href="http://www.ezsky.org"  rel="external nofollow"  class="url" >ezsky</a> writes: 在这也能碰上熟人.</li><li><a href="http://www.laruence.com/2010/06/22/1618.html#comment-2851" >2010/06/27</a>, 烂叶 writes: 鸟哥出东西。都是好东西。</li><li><a href="http://www.laruence.com/2010/06/22/1618.html#comment-2865" >2010/06/30</a>, wangchao writes: array_walk($keys, 'trimblank');
function trimblank(&amp;$var) {
    $var = trim($var);
    return $var;
}
上面可以去除数组中元素的空白
但是
array_walk($keys, 'trimblank');
function trimblank(&amp;$var) {
    return trim($var);
}
就不能去除空白了，这个是为什么啊。请赐教。</li><li><a href="http://www.laruence.com/2010/06/22/1618.html#comment-2993" >2010/07/27</a>, <a href="http://www.commentset.com"  rel="external nofollow"  class="url" >mahone</a> writes: 好文，已阅。只是这上面的很多文章都有点看不懂</li></ul><hr/><small  style="font-size:85%;font-size:85%;">Copyright &copy; 2010 <a href="http://www.laruence.com"  target="_blank" >风雪之隅</a> 版权所有, 转载务必注明. 该Feed只供个人使用, 禁止未注明的转载或商业应用. 非法应用的, 一切法律后果自负. 如有问题, 可发E-mail至my at laruence.com.(Digital Fingerprint: 73540ba0a1738d7d07d4b6038d5615e2)</small>]]></content:encoded>
			<wfw:commentRss>http://www.laruence.com/2010/06/22/1618.html/feed</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>PHP调试技术手册发布(1.0.0 pdf)</title>
		<link>http://www.laruence.com/2010/06/21/1608.html</link>
		<comments>http://www.laruence.com/2010/06/21/1608.html#comments</comments>
		<pubDate>Mon, 21 Jun 2010 05:31:22 +0000</pubDate>
		<dc:creator>雪候鸟</dc:creator>
				<category><![CDATA[PHP应用]]></category>
		<category><![CDATA[debug]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[手册]]></category>
		<category><![CDATA[调试技术]]></category>

		<guid isPermaLink="false">http://www.laruence.com/?p=1608</guid>
		<description><![CDATA[   <a href="http://blog.csdn.net/heiyeshuwu" target="_blank">黑夜路人</a>前段时间, 本着分享/总结的精神, 计划要总结下PHP常用的调试技术, 就一些问题找到了我..

   如今第一版的PHP调试技术手册已经发布.

   冠以我名, 我甚感惶恐, 只能一并赞下小黑的nice了~

   下载地址: <a href="http://heiyeluren-doc.googlecode.com/files/PHP-Debug-Manual-public.pdf">http://heiyeluren-doc.googlecode.com/files/PHP-Debug-Manual-public.pdf</a>]]></description>
			<content:encoded><![CDATA[<div class="copyright" >
<ul  style="padding-left:1em;font-size:85%;padding-left:1em;font-size:85%;">
<li>作者: laruence(<a href="http://www.laruence.com"  title="风雪之隅"  target="_blank" >http://www.laruence.com</a>)</li>
<li>本文地址: <a href="http://www.laruence.com/2010/06/21/1608.html"  title="Permanet Link to PHP调试技术手册发布(1.0.0 pdf)" >http://www.laruence.com/2010/06/21/1608.html</a></li>
<li>转载请注明出处 </li>
</ul></div>
<p>
   <a href="http://blog.csdn.net/heiyeshuwu"  target="_blank" >黑夜路人</a>前段时间, 本着分享/总结的精神, 计划要总结下PHP常用的调试技术, 就一些问题找到了我..</p>
<p>   如今第一版的PHP调试技术手册已经发布.</p>
<p>   冠以我名, 我甚感惶恐, 只能一并赞下小黑的nice了~</p>
<p>   下载地址: <a href="http://heiyeluren-doc.googlecode.com/files/PHP-Debug-Manual-public.pdf" >http://heiyeluren-doc.googlecode.com/files/PHP-Debug-Manual-public.pdf</a></p>
<p>   目录:</p>
<pre name="code"  class="sh_bash"  linenum="off"   style="background: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:Monacobackground: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:MonacoConsolasConsolasCourierCouriermonospace;monospace;">
1 内置API输出调试
1.1 基本调试API
1.1.1 echo (print):
1.1.2 printf
1.1.3 print_r、var_dump(var_export)、debug_zval_dump
1.2 错误控制和日志记录调试
1.2.1 错误选项控制
1.2.2 错误抛出和处理
1.2.3 使用错误抑制符
1.2.4 日志记录
2 浏览器调试
2.1 页面输出调试
2.2 FirePHP  调试
2.2.1 普通变量监测
2.2.2 调用栈监测
2.2.3 监测抛出异常
2.2.4 组显示信息
3 IDE 调试
3.1 基本常用IDE介绍
3.1.1 Vim
3.1.2 Zend Studio
3.1.3 Eclipse
3.1.4 NetBeans
3.2 IDE调试
3.2.1 Zend Studio + Zend Debugger
3.2.2 Eclipse (PDT) + Xdebug
3.2.3 Vim + Xdebug + DBGp
4 PHP 性能调试技术
4.1 基本时间占用监测
4.2 使用  Xdebug 进行性能分析
4.2.1 安装配置：
4.3 APD(Advanced PHP Debugger)
4.3.1 安装配置
4.3.2 使用APD
4.4 使用Xhprof 进行性能分析
4.4.1 Xhprof  的优点：
5 PHP单元测试技术
5.1 PHPUnit
</pre>
<p><script type="text/javascript"  src="http://www.laruence.com/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_bash.js" ></script></p>
<hr/><h2>Comments</h2><ul  style="padding-left:1em;font-size:85%;padding-left:1em;font-size:85%;"><li><a href="http://www.laruence.com/2010/06/21/1608.html#comment-2771" >2010/06/21</a>, 小熊 writes: 阅</li><li><a href="http://www.laruence.com/2010/06/21/1608.html#comment-2772" >2010/06/21</a>, <a href="http://www.zvv.cn"  rel="external nofollow"  class="url" >zwws</a> writes: 好东西, 已经发到部门共享了, 赞一个!</li><li><a href="http://www.laruence.com/2010/06/21/1608.html#comment-2773" >2010/06/21</a>, <a href="http://www.xinqdian.com"  rel="external nofollow"  class="url" >小宝</a> writes: 这个绝对得支持下！</li><li><a href="http://www.laruence.com/2010/06/21/1608.html#comment-2774" >2010/06/21</a>, qxhy123 writes: 迅速插入前5</li><li><a href="http://www.laruence.com/2010/06/21/1608.html#comment-2775" >2010/06/21</a>, marker writes: 顶呀</li><li><a href="http://www.laruence.com/2010/06/21/1608.html#comment-2776" >2010/06/21</a>, <a href="http://topsy.com/www.laruence.com/2010/06/21/1608.html?utm_source=pingback&amp;utm_campaign=L2"  rel="external nofollow"  class="url" >Tweets that mention PHP调试技术手册发布(1.0.0 pdf) | 风雪之隅 -- Topsy.com</a> writes: [...] This post was mentioned on Twitter by icyleaf, cunsheng. cunsheng said: PHP调试技术手册发布(1.0.0 pdf) http://ff.im/-mqIlL [...]</li><li><a href="http://www.laruence.com/2010/06/21/1608.html#comment-2777" >2010/06/21</a>, <a href="http://www.youyuge.com"  rel="external nofollow"  class="url" >xiaokai</a> writes: 来的还不算晚..</li><li><a href="http://www.laruence.com/2010/06/21/1608.html#comment-2779" >2010/06/21</a>, <a href="http://sychen.org"  rel="external nofollow"  class="url" >sychen</a> writes: 顶，值得拜读~</li><li><a href="http://www.laruence.com/2010/06/21/1608.html#comment-2780" >2010/06/21</a>, <a href="http://lepingbeta.com"  rel="external nofollow"  class="url" >Symphony</a> writes: 超赞，这个不能不顶啊。。。</li><li><a href="http://www.laruence.com/2010/06/21/1608.html#comment-2781" >2010/06/21</a>, <a href="http://www.9enjoy.com"  rel="external nofollow"  class="url" >9enjoy</a> writes: 好东西，学习一下。</li><li><a href="http://www.laruence.com/2010/06/21/1608.html#comment-2783" >2010/06/21</a>, <a href="http://glemir.xplore.cn"  rel="external nofollow"  class="url" >glemir</a> writes: 很给力啊，老湿</li><li><a href="http://www.laruence.com/2010/06/21/1608.html#comment-2785" >2010/06/21</a>, <a href="http://hjin.me"  rel="external nofollow"  class="url" >HJin.me</a> writes: 作为一个php学习生，看到这样的好东西，自然留言以表示对博主的感谢～～～</li><li><a href="http://www.laruence.com/2010/06/21/1608.html#comment-2788" >2010/06/22</a>, <a href="http://0xs.cn/"  rel="external nofollow"  class="url" >潇洒</a> writes: 呵呵~ 既然收了，就得留个脚印...
不知有木有时间看哈...</li><li><a href="http://www.laruence.com/2010/06/21/1608.html#comment-2831" >2010/06/23</a>, <a href="http://www.zhangabc.com"  rel="external nofollow"  class="url" >yufeng</a> writes: 学习啊，特别是vim调试那节，找个时间实验一下，有时var_dump\print_r真的很烦。</li><li><a href="http://www.laruence.com/2010/06/21/1608.html#comment-2834" >2010/06/23</a>, <a href="http://www.pentestday.com/2010/06/php-debug-manual-version-1-0-0.html"  rel="external nofollow"  class="url" >PHP调试技术手册 | Pentestday</a> writes: [...] v1.0.0 Posted on June 23, 2010 by xi4oyu* 作者: laruence(http://www.laruence.com) * 本文地址: http://www.laruence.com/2010/06/21/1608.html * 转载请注明出处黑夜路人前段时间, 本着分享/总结的精神, [...]</li><li><a href="http://www.laruence.com/2010/06/21/1608.html#comment-2835" >2010/06/24</a>, <a href="http://www.mkrss.com/?p=52"  rel="external nofollow"  class="url" >PHP调试技术手册发布(1.0.0 pdf) &laquo; Yet another wordpress blog</a> writes: [...] 本文地址: http://www.laruence.com/2010/06/21/1608.html [...]</li><li><a href="http://www.laruence.com/2010/06/21/1608.html#comment-2840" >2010/06/24</a>, z.En writes: 很有用</li><li><a href="http://www.laruence.com/2010/06/21/1608.html#comment-2842" >2010/06/24</a>, <a href="http://www.pentestday.com"  rel="external nofollow"  class="url" >xi4oyu</a> writes: 顶，转载了</li><li><a href="http://www.laruence.com/2010/06/21/1608.html#comment-2850" >2010/06/27</a>, <a href="http://www.zhangabc.com/?p=142"  rel="external nofollow"  class="url" >ZhangABC.com &raquo; 向printechovar_dump说再见,用VIM来调试PHP程序</a> writes: [...] &gt;(详见鸟哥此文，强力推荐). [...]</li><li><a href="http://www.laruence.com/2010/06/21/1608.html#comment-2864" >2010/06/29</a>, <a href="http://sanmuding.com"  rel="external nofollow"  class="url" >Anders</a> writes: 呵呵，好怀念PHP阿。</li><li><a href="http://www.laruence.com/2010/06/21/1608.html#comment-2867" >2010/07/01</a>, <a href="http://www.yakecan.com/archives/386"  rel="external nofollow"  class="url" >&raquo; Creative Power</a> writes: [...] 原文地址: http://www.laruence.com/2010/06/21/1608.html [...]</li><li><a href="http://www.laruence.com/2010/06/21/1608.html#comment-2869" >2010/07/02</a>, <a href="http://xiaobin.net/201007/using-vim-and-xdebug-to-debug-php-code/"  rel="external nofollow"  class="url" >Vim+XDebug调试PHP | 将之典藏</a> writes: [...] 感谢老黑和鸟哥发布的《PHP调试指南》(via)。要不是他们，我可能还在用echo/var_dump调试PHP代码。是他们解救了我，引导我走向光明，感激涕零中……本文是对指南中的《Vim + Xdebug + DBGp》一章的一些补充。 [...]</li><li><a href="http://www.laruence.com/2010/06/21/1608.html#comment-2886" >2010/07/06</a>, Luffy writes: 一口氣看完~真的很讚, 若果UNIT TEST都可以寫得詳盡點就完美了.</li><li><a href="http://www.laruence.com/2010/06/21/1608.html#comment-2908" >2010/07/09</a>, <a href="http://www.js4j.com/"  rel="external nofollow"  class="url" >技术论坛</a> writes: 拜读</li><li><a href="http://www.laruence.com/2010/06/21/1608.html#comment-2942" >2010/07/16</a>, <a href="http://dothing"  rel="external nofollow"  class="url" >lake</a> writes: 非常好，收藏了。多谢高手的分享。</li><li><a href="http://www.laruence.com/2010/06/21/1608.html#comment-2964" >2010/07/19</a>, <a href="http://www.ezsky.org"  rel="external nofollow"  class="url" >ezsky</a> writes: 收藏了!
支持,感谢.</li><li><a href="http://www.laruence.com/2010/06/21/1608.html#comment-3096" >2010/08/21</a>, <a href="http://blog.pptpb.org/2010/08/21/337"  rel="external nofollow"  class="url" >雨季來了 &raquo; link notes</a> writes: [...] PHP調試技術手冊 [...]</li><li><a href="http://www.laruence.com/2010/06/21/1608.html#comment-3113" >2010/08/25</a>, <a href="http://www.bestfinance-blog.com"  rel="external nofollow"  class="url" >CarissaAlford27</a> writes: That is cool that people are able to receive the <a href="http://bestfinance-blog.com/topics/home-loans"  rel="nofollow" >home loans</a> moreover, that opens completely new opportunities.</li><li><a href="http://www.laruence.com/2010/06/21/1608.html#comment-3114" >2010/08/26</a>, <a href="http://www.airmaxtrainer.com"  rel="external nofollow"  class="url" >air max shoes</a> writes: 很好用哦  谢谢！</li></ul><hr/><small  style="font-size:85%;font-size:85%;">Copyright &copy; 2010 <a href="http://www.laruence.com"  target="_blank" >风雪之隅</a> 版权所有, 转载务必注明. 该Feed只供个人使用, 禁止未注明的转载或商业应用. 非法应用的, 一切法律后果自负. 如有问题, 可发E-mail至my at laruence.com.(Digital Fingerprint: 73540ba0a1738d7d07d4b6038d5615e2)</small>]]></content:encoded>
			<wfw:commentRss>http://www.laruence.com/2010/06/21/1608.html/feed</wfw:commentRss>
		<slash:comments>29</slash:comments>
		</item>
		<item>
		<title>深入理解PHP之匿名函数</title>
		<link>http://www.laruence.com/2010/06/20/1602.html</link>
		<comments>http://www.laruence.com/2010/06/20/1602.html#comments</comments>
		<pubDate>Sun, 20 Jun 2010 14:41:58 +0000</pubDate>
		<dc:creator>雪候鸟</dc:creator>
				<category><![CDATA[PHP应用]]></category>
		<category><![CDATA[anonymous function]]></category>
		<category><![CDATA[closure]]></category>
		<category><![CDATA[create_function]]></category>
		<category><![CDATA[lambda function]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[匿名函数]]></category>
		<category><![CDATA[闭包]]></category>

		<guid isPermaLink="false">http://www.laruence.com/?p=1602</guid>
		<description><![CDATA[	PHP中, 传递Callback的方式, 一直很丑陋. 在PHP5.3以前, 我们只有俩种选择:
<coolcode lang="bash" linenum="off">
1. 字符串的函数名
2. 使用create_function的返回值
</coolcode>
	在PHP5.3以后, 我们多了一个选择, 也就是Closure, 
<coolcode lang="php" linenum="off">
$func = function () { ... };
array_walk($arr, $func);
</coolcode>]]></description>
			<content:encoded><![CDATA[<div class="copyright" >
<ul  style="padding-left:1em;font-size:85%;padding-left:1em;font-size:85%;">
<li>作者: laruence(<a href="http://www.laruence.com"  title="风雪之隅"  target="_blank" >http://www.laruence.com</a>)</li>
<li>本文地址: <a href="http://www.laruence.com/2010/06/20/1602.html"  title="Permanet Link to 深入理解PHP之匿名函数" >http://www.laruence.com/2010/06/20/1602.html</a></li>
<li>转载请注明出处 </li>
</ul></div>
<p>
	PHP中, 传递Callback的方式, 一直很丑陋. 在PHP5.3以前, 我们只有俩种选择:</p>
<pre name="code"  class="sh_bash"  linenum="off"   style="background: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:Monacobackground: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:MonacoConsolasConsolasCourierCouriermonospace;monospace;">
1. 字符串的函数名
2. 使用create_function的返回值
</pre>
<p>	在PHP5.3以后, 我们多了一个选择, 也就是Closure, </p>
<pre name="code"  class="sh_php"  linenum="off"   style="background: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:Monacobackground: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:MonacoConsolasConsolasCourierCouriermonospace;monospace;">
$func = function () { ... };
array_walk($arr, $func);
</pre>
<p>	从实现上来说, 第一种方式: 传递函数名字符串是最简单的.</p>
<p>	而第二种方式create_function, 其实和第一种方式本质上一样的, create_function返回一个字符串的函数名, 这个函数名的格式是:</p>
<pre name="code"  class="sh_bash"  linenum="off"   style="background: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:Monacobackground: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:MonacoConsolasConsolasCourierCouriermonospace;monospace;">
&quot;\000_lambda_&quot; . count(anonymous_functions)++;
</pre>
<p>	我们来看看create_function的实现步骤:</p>
<pre name="code"  class="sh_bash"  linenum="off"   style="background: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:Monacobackground: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:MonacoConsolasConsolasCourierCouriermonospace;monospace;">
1. 获取参数, 函数体
2. 拼凑一个&quot;function __lambda_func (参数) { 函数体;} &quot;的字符串
3. eval之
4. 通过__lambda_func在函数表中找到eval后得到的函数体, 找不到就出错
5. 定义一个函数名:&quot;\000_lambda_&quot; . count(anonymous_functions)++
6. 用新的函数名替换__lambda_func
7. 返回新的函数名
</pre>
<p>	我们来验证下:</p>
<pre name="code"  class="sh_php"  linenum="off"   style="background: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:Monacobackground: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:MonacoConsolasConsolasCourierCouriermonospace;monospace;">
&lt;?php
create_function(&quot;&quot;, 'echo __FUNCTION__;');
call_user_func(&quot;\000lambda_1&quot;, 1);
?&gt;
//输出
__lambda_func
</pre>
<p>	因为在eval的时候, 函数名是&#8221;__lambda_func&#8221;, 所以匿名函数内会输出__lambda_func, 而因为最后用&#8221;\000_lambda_&#8221; . count(anonymous_functions)++重命名了函数表中的&#8221;__lambda_func&#8221;函数, 所以可通过&#8221;\000_lambda_&#8221; . count(anonymous_functions)++调用这个匿名函数.</p>
<p>	为了证实这一点, 可以将create_function的返回值dump出来查看.</p>
<p>	而在PHP5.3发布的时候, 其中有一条new feature就是支持闭包/Lambda Function, 我第一反应是以为zval新增了一个IS_FUNCTION, 但实际上是构造了一个PHP5.3引入的Closure&#8221;类&#8221;的实例, Closure类的构造函数是私有的, 所以不能被直接实例化, 另外Closure类是Final类, 所以也不能做为基类派生子类.</p>
<pre name="code"  class="sh_php"  linenum="off"   style="background: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:Monacobackground: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:MonacoConsolasConsolasCourierCouriermonospace;monospace;">
//php-5.3.0
$class = new ReflectionClass(&quot;Closure&quot;);
var_dump($class-&gt;isInternal());
var_dump($class-&gt;isAbstract() );
var_dump($class-&gt;isFinal());
var_dump($class-&gt;isInterface());
//输出:
bool(true)
bool(false)
bool(true)
bool(false)
?&gt;
</pre>
<p>	而PHP5.3中对闭包的支持, 也仅仅是把要保持的外部变量, 做为Closure对象的&#8221;Static属性&#8221;(并不是普通意义上的可遍历/访问的属性).</p>
<pre name="code"  class="sh_php"  linenum="off"   style="background: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:Monacobackground: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:MonacoConsolasConsolasCourierCouriermonospace;monospace;">
//php-5.3.0
$b = &quot;laruence&quot;;
$func = function($a) use($b) {};
var_dump($func);
/* 输出:
object(Closure)#1 (2) {
  [&quot;static&quot;]=&gt;
  array(1) {
    [&quot;b&quot;]=&gt;
    string(8) &quot;laruence&quot;
  }
  [&quot;parameter&quot;]=&gt;
  array(1) {
    [&quot;$a&quot;]=&gt;
    string(10) &quot;&lt;required&gt;&quot;
  }
}
*/
</pre>
<p>     这个实现, 个人认为和JS对闭包的支持比起来, 还是有些太简陋了~<br/>
<script type="text/javascript"  src="http://www.laruence.com/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_bash.js" ></script><script type="text/javascript"  src="http://www.laruence.com/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_php.js" ></script><script type="text/javascript"  src="http://www.laruence.com/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_bash.js" ></script><script type="text/javascript"  src="http://www.laruence.com/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_bash.js" ></script><script type="text/javascript"  src="http://www.laruence.com/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_php.js" ></script><script type="text/javascript"  src="http://www.laruence.com/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_php.js" ></script><script type="text/javascript"  src="http://www.laruence.com/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_php.js" ></script></p>
<hr/><h2>Comments</h2><ul  style="padding-left:1em;font-size:85%;padding-left:1em;font-size:85%;"><li><a href="http://www.laruence.com/2010/06/20/1602.html#comment-2767" >2010/06/20</a>, <a href="http://www.elmerzhang.com"  rel="external nofollow"  class="url" >ElmerZhang</a> writes: 第二种方式create_function 的代码贴错了吧？</li><li><a href="http://www.laruence.com/2010/06/20/1602.html#comment-2768" >2010/06/20</a>, <a href="http://www.laruence.com"  rel="external nofollow"  class="url" >雪候鸟</a> writes: @ElmerZhang 没有啊? 你是指哪里错了?</li><li><a href="http://www.laruence.com/2010/06/20/1602.html#comment-2770" >2010/06/21</a>, <a href="http://www.elmerzhang.com"  rel="external nofollow"  class="url" >ElmerZhang</a> writes: 不好意思，是我看错了，呵呵</li><li><a href="http://www.laruence.com/2010/06/20/1602.html#comment-2784" >2010/06/21</a>, <a href="http://syre.blogbus.com"  rel="external nofollow"  class="url" >神仙</a> writes: 底子差，没办法。</li><li><a href="http://www.laruence.com/2010/06/20/1602.html#comment-2829" >2010/06/22</a>, wynn writes: Closure机制的编写者在RFC里有提到这个问题，基本意思就是说这方面不是PHP的核心机制，因此不会在这方面下太多力气。</li><li><a href="http://www.laruence.com/2010/06/20/1602.html#comment-2836" >2010/06/24</a>, <a href="http://www.mkrss.com/?p=53"  rel="external nofollow"  class="url" >深入理解PHP之匿名函数 &laquo; Yet another wordpress blog</a> writes: [...] 本文地址: http://www.laruence.com/2010/06/20/1602.html [...]</li><li><a href="http://www.laruence.com/2010/06/20/1602.html#comment-2837" >2010/06/24</a>, <a href="http://www.jaceju.net/blog/?p=1245"  rel="external nofollow"  class="url" >網站製作學習誌 &raquo; [Web] 連結分享</a> writes: [...] 深入理解PHP之匿名函数 [...]</li><li><a href="http://www.laruence.com/2010/06/20/1602.html#comment-3029" >2010/08/03</a>, <a href="http://www.yeeger.com/?p=167"  rel="external nofollow"  class="url" >深入理解PHP之匿名函数 | yeeger.com</a> writes: [...] 转自： http://www.laruence.com/2010/06/20/1602.html     发表评论 | Trackback   2010年8月3日 | 归档于 编程高手  标签: PHP, 匿名函数, 闭包      &laquo; MyISAM和InnoDB两种引擎的区别       本文目前尚无任何评论. [...]</li></ul><hr/><small  style="font-size:85%;font-size:85%;">Copyright &copy; 2010 <a href="http://www.laruence.com"  target="_blank" >风雪之隅</a> 版权所有, 转载务必注明. 该Feed只供个人使用, 禁止未注明的转载或商业应用. 非法应用的, 一切法律后果自负. 如有问题, 可发E-mail至my at laruence.com.(Digital Fingerprint: 73540ba0a1738d7d07d4b6038d5615e2)</small>]]></content:encoded>
			<wfw:commentRss>http://www.laruence.com/2010/06/20/1602.html/feed</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
		<item>
		<title>深悉正则(pcre)最大回溯/递归限制</title>
		<link>http://www.laruence.com/2010/06/08/1579.html</link>
		<comments>http://www.laruence.com/2010/06/08/1579.html#comments</comments>
		<pubDate>Tue, 08 Jun 2010 11:44:36 +0000</pubDate>
		<dc:creator>雪候鸟</dc:creator>
				<category><![CDATA[PHP应用]]></category>
		<category><![CDATA[PHP源码分析]]></category>
		<category><![CDATA[backtrack_limit]]></category>
		<category><![CDATA[pcre]]></category>
		<category><![CDATA[PREG_BACKTRACK_LIMIT_ERROR]]></category>
		<category><![CDATA[recursion_limit]]></category>

		<guid isPermaLink="false">http://www.laruence.com/?p=1579</guid>
		<description><![CDATA[    今天,Tank问了一个问题, 对于如下的正则:
<coolcode lang="bash" linenum="off">
/<script>.*?<\/script>/is
</coolcode>

	当要匹配的字符串长度<b>大于</b>100014的时候, 就<b>不会</b>得出正确结果:
<coolcode lang="php" linenum="off">
$reg = "/<script>.*?<\/script>/is";
$str = "<script>********</script>"; //长度大于100014
$ret = preg_replace($reg, "", $str); //返回NULL
</coolcode>

	难道正则对匹配的串有长度限制?]]></description>
			<content:encoded><![CDATA[<div class="copyright" >
<ul  style="padding-left:1em;font-size:85%;padding-left:1em;font-size:85%;">
<li>作者: laruence(<a href="http://www.laruence.com"  title="风雪之隅"  target="_blank" >http://www.laruence.com</a>)</li>
<li>本文地址: <a href="http://www.laruence.com/2010/06/08/1579.html"  title="Permanet Link to 深悉正则(pcre)最大回溯/递归限制" >http://www.laruence.com/2010/06/08/1579.html</a></li>
<li>转载请注明出处 </li>
</ul></div>
<p>
    今天,<a href="http://www.skiyo.cn/"  target="_blank" >Tank</a>问了一个问题, 对于如下的正则:</p>
<pre name="code"  class="sh_bash"  linenum="off"   style="background: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:Monacobackground: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:MonacoConsolasConsolasCourierCouriermonospace;monospace;">
/&lt;script&gt;.*?&lt;\/script&gt;/is
</pre>
<p>	当要匹配的字符串长度<b>大于</b>100014的时候, 就<b>不会</b>得出正确结果:</p>
<pre name="code"  class="sh_php"  linenum="off"   style="background: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:Monacobackground: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:MonacoConsolasConsolasCourierCouriermonospace;monospace;">
$reg = &quot;/&lt;script&gt;.*?&lt;\/script&gt;/is&quot;;
$str = &quot;&lt;script&gt;********&lt;/script&gt;&quot;; //长度大于100014
$ret = preg_replace($reg, &quot;&quot;, $str); //返回NULL
</pre>
<p>	难道正则对匹配的串有长度限制?</p>
<p>	不是, 当然不是, 原因是这样的, 在PHP的pcre扩展中, 提供了俩个设置项.</p>
<pre name="code"  class="sh_php"  linenum="off"   style="background: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:Monacobackground: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:MonacoConsolasConsolasCourierCouriermonospace;monospace;">
1. pcre.backtrack_limit //最大回溯数
2. pcre.recursion_limit //最大嵌套数
</pre>
<p>	默认的backtarck_limit是100000(10万).</p>
<p>	这个问题, 就和设置项backtrack_limit有关系. 现在要弄清这个问题的原因, 关键就是什么是&#8221;回溯&#8221;.</p>
<p>	这个正则, 使用非贪婪模式, 非贪婪模式匹配原理简单来说是, 在可配也可不配的情况下, 优先不匹配. 记录备选状态, 并将匹配控制交给正则表达式的下一个匹配字符, 当之后的匹配失败的时候, 再溯, 进行匹配.</p>
<p>	举个例子:</p>
<pre name="code"  class="sh_bash"  linenum="off"   style="background: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:Monacobackground: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:MonacoConsolasConsolasCourierCouriermonospace;monospace;">
源字符串: aaab
正则:     .*?b
</pre>
<p>	匹配过程开始的时候, &#8220;.*?&#8221;首先取得匹配控制权, 因为是非贪婪模式, 所以优先不匹配, 将匹配控制交给下一个匹配字符&#8221;b&#8221;, &#8220;b&#8221;在源字符串位置1匹配失败(&#8220;a&#8221;), 于是回溯, 将匹配控制交回给&#8221;.*?&#8221;, 这个时候, &#8220;.*?&#8221;匹配一个字符&#8221;a&#8221;, 并再次将控制权交给&#8221;b&#8221;, 如此反复, 最终得到匹配结果, 这个过程中一共发生了3次回溯.</p>
<p>	现在我们来看看文章开头的例子,  默认的backtrack_limit是100000, 而源字符串的开头是<script>, 8个字符, 匹配这个过程中没有回溯, 现在进入到了.*?, 因为整个字符串的长度是100014, 去掉头的<script>的8个字符是100006, 再减去尾部的</script>9个字符, 一共是99997个字符.</p>
<p>    另外, 因为match函数自身的逻辑, 在文章开头的例子下, 会导致回溯计数增3(有兴趣的可以参看pcrelib/pcre_exec.c中match函数逻辑部分), 所以在匹配到"</script>&#8220;之前, pcre中的回溯计数刚好是100000,于是就正常匹配, 退出.</p>
<p>	而, 只要在增加一个字符, 就会导致回溯计数大于100000, 从而导致匹配失败退出.</p>
<p>    在PHP 5.2以后, 提供了:</p>
<pre name="code"  class="sh_c"  linenum="off"   style="background: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:Monacobackground: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:MonacoConsolasConsolasCourierCouriermonospace;monospace;">
int preg_last_error ( void )
Returns the error code of the last PCRE regex execution.
</pre>
<p>	我们应该经常检查这个函数的返回值,  当不为零的时候说明上一个正则函数出错,  特别的对于文章的例子, 出错返回(PREG_BACKTRACK_LIMIT_ERROR)</p>
<p>	最后, 在顺便说一句, 非贪婪模式导致太多回溯, 必然会有一些性能问题,  适当的该写下正则, 是可以避免这个问题的. 比如将文章开头例子中的正则修改为:</p>
<pre name="code"  class="sh_bash"  linenum="off"   style="background: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:Monacobackground: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:MonacoConsolasConsolasCourierCouriermonospace;monospace;">
/&lt;script&gt;[^&lt;]*&lt;\/script&gt;/is
</pre>
<p>	就不会导致这么多的回溯了~</p>
<p>        而recursion_limit限制了最大的正则嵌套层数, 如果这个值, 设置的太大, 可能会造成耗尽栈空间爆栈. 默认的100000似乎有点太大了&#8230; </p>
<p>        就比如对于一个长度为10000的字符串, 如下这个看似&#8221;简&#8221;的单正则:</p>
<pre name="code"  class="sh_php"  linenum="off"   style="background: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:Monacobackground: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:MonacoConsolasConsolasCourierCouriermonospace;monospace;">
//默认recursion_limit为100000
$reg = /(.+?)+/is;
$str = str_pad(&quot;laruence&quot;, 10000, &quot;a&quot;); //长度为1万
$ret = preg_repalce($reg, &quot;&quot;, $str);
</pre>
<p>        会导致core, 这是因为嵌套太多, 导致爆栈. </p>
<p>        当然, 你可以通过修改栈的大小来暂时的解决这个问题, 比如修改栈空间为20M以后, 上面的代码就能正常运行, 但这肯定不是最完美的解法.  根本之道, 还是优化正则.</p>
<p>       最后: <b>正则虽易, 用好却难.</b>.  尤其在做大数据量的文本处理的时候, 如果正则设计不慎, 很容易导致深度嵌套, 另外考虑到性能, 还是建议能用字符串处理尽量使用字符串处理代替.<script type="text/javascript"  src="http://www.laruence.com/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_bash.js" ></script><script type="text/javascript"  src="http://www.laruence.com/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_php.js" ></script><script type="text/javascript"  src="http://www.laruence.com/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_php.js" ></script><script type="text/javascript"  src="http://www.laruence.com/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_bash.js" ></script><script type="text/javascript"  src="http://www.laruence.com/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_c.js" ></script><script type="text/javascript"  src="http://www.laruence.com/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_bash.js" ></script><script type="text/javascript"  src="http://www.laruence.com/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_php.js" ></script></p>
<hr/><h2>Comments</h2><ul  style="padding-left:1em;font-size:85%;padding-left:1em;font-size:85%;"><li><a href="http://www.laruence.com/2010/06/08/1579.html#comment-2719" >2010/06/08</a>, <a href="http://skiyo.cn"  rel="external nofollow"  class="url" >Skiyo</a> writes: 明白了哈 多谢鸟哥</li><li><a href="http://www.laruence.com/2010/06/08/1579.html#comment-2722" >2010/06/09</a>, 小熊 writes: 还有这等事，学习了。
劳伦斯威武</li><li><a href="http://www.laruence.com/2010/06/08/1579.html#comment-2723" >2010/06/09</a>, <a href="http://www.zhangabc.com"  rel="external nofollow"  class="url" >yufeng</a> writes: 学习……同时回忆正则。</li><li><a href="http://www.laruence.com/2010/06/08/1579.html#comment-2724" >2010/06/09</a>, <a href="http://syre.blogbus.com"  rel="external nofollow"  class="url" >神仙</a> writes: 记得还有正则表达式的最大长度限制，默认貌似是64k</li><li><a href="http://www.laruence.com/2010/06/08/1579.html#comment-2725" >2010/06/09</a>, 〤依然特雷西 writes: 谢谢鸟哥..解释出了我 在PPC上的困惑的问题..http://bbs.phpchina.com/thread-184862-1-1.html</li><li><a href="http://www.laruence.com/2010/06/08/1579.html#comment-2726" >2010/06/09</a>, <a href="http://www.laruence.com"  rel="external nofollow"  class="url" >雪候鸟</a> writes: @神仙 恩,是有这个限制, 不过一般来说, 这个限制咱们倒不会触及, :)</li><li><a href="http://www.laruence.com/2010/06/08/1579.html#comment-2728" >2010/06/10</a>, <a href="http://www.idea78.com"  rel="external nofollow"  class="url" >创意网</a> writes: 学习……同时回忆正则。.....</li><li><a href="http://www.laruence.com/2010/06/08/1579.html#comment-2734" >2010/06/10</a>, <a href="www.phppan.com"  rel="external nofollow"  class="url" >胖子</a> writes: 学习了，回忆正则</li><li><a href="http://www.laruence.com/2010/06/08/1579.html#comment-2735" >2010/06/10</a>, <a href="http://www.laruence.com"  rel="external nofollow"  class="url" >雪候鸟</a> writes: @胖子 你们的队形很整齐.</li><li><a href="http://www.laruence.com/2010/06/08/1579.html#comment-2741" >2010/06/11</a>, N writes: 1.开头的正则是不小心写错的吗？

2.用非贪婪匹配的话，回溯数就是最小匹配的字符数，文章中说到因为match自身的逻辑，回溯数会加3，那么“********”中的"*****"长度超过99997(100000-3)就会匹配失败，我是这么理解的。但是“因为默认的backtrack_limit是100000, 源字符串的开头是9 个字符, 一共是99997个字符.”这句话我没看明白。</li><li><a href="http://www.laruence.com/2010/06/08/1579.html#comment-2742" >2010/06/11</a>, <a href="http://www.laruence.com"  rel="external nofollow"  class="url" >雪候鸟</a> writes: @N 谢谢指正,是写错了, 手误. 至于第二个问题, 你是哪里没看明白呢?</li><li><a href="http://www.laruence.com/2010/06/08/1579.html#comment-2753" >2010/06/11</a>, 饼饼 writes: 匹配过程开始的时候, “.*?”首先取得匹配控制权, 因为是非贪婪模式
.*? 这个不算贪婪么？</li><li><a href="http://www.laruence.com/2010/06/08/1579.html#comment-2754" >2010/06/12</a>, <a href="http://syre.blogbus.com"  rel="external nofollow"  class="url" >神仙</a> writes: 我最开始用正则表达式来搞关键词匹配，词少的时候没事，词一多就撞上那个限制了……
然后php的pcre包里没那个dfa, nfa的转换</li><li><a href="http://www.laruence.com/2010/06/08/1579.html#comment-2755" >2010/06/14</a>, <a href="###"  rel="external nofollow"  class="url" >shzhrui</a> writes: $reg 也存在长度过大会出错
每当国家各种会议期间，都会有大量的关键词要屏蔽。
目前只能分批进行匹配，这样做在性能方法定有所下降。，不知高人有何其它解决方法。或者从原理上给分析下。。</li><li><a href="http://www.laruence.com/2010/06/08/1579.html#comment-2759" >2010/06/17</a>, <a href="http://brhum.org"  rel="external nofollow"  class="url" >Brhum</a> writes: 你这个wp主题在IE6下乱的不成样子~~~~</li><li><a href="http://www.laruence.com/2010/06/08/1579.html#comment-2778" >2010/06/21</a>, <a href="http://www.cnxct.com/%e5%b0%8f%e8%ae%ae%e6%ad%a3%e5%88%99%e8%a1%a8%e8%be%be%e5%bc%8f%e6%95%88%e7%8e%87%ef%bc%9a%e8%b4%aa%e5%a9%aa%e3%80%81%e9%9d%9e%e8%b4%aa%e5%a9%aa%e4%b8%8e%e5%9b%9e%e6%ba%af/"  rel="external nofollow"  class="url" >小议正则表达式效率：贪婪、非贪婪与回溯 | CNXCT小组的博客</a> writes: [...] 前几天看了鸟哥的BLOG上写的关于正则表达式的回溯与递归的限制时，对贪婪、非贪婪产生的回溯有疑问，遂近段时间，仔细的学习研究了一下，现在把经验心得与大家分享一下。 （我日，这里好像被左侧的图挡着了，换行换行凑字数，换行换行凑字数，换行换行凑字数，换行换行凑字数，换行换行凑字数，换行换行凑字数，换行换行凑字数，换行换行凑字数，换行换行凑字数，换行换行凑字数，换行换行凑字数，换行换行凑字数，换行换行凑字数，换行换行凑字数，换行换行凑字数） 先扫盲一下什么是正则表达式的贪婪，什么是非贪婪？或者说什么是匹配优先量词，什么是忽略优先量词？ 好吧，我也不知道概念是什么，来举个例子吧。 某同学想过滤....之间的内容，那是这么写正则以及程序的。 [...]</li><li><a href="http://www.laruence.com/2010/06/08/1579.html#comment-2782" >2010/06/21</a>, <a href="http://www.cnxct.com"  rel="external nofollow"  class="url" >CFC4N</a> writes: 鸟哥，函数写错了
$ret = preg_repalce($reg, "", $str);
应该是preg_repLAce..手误哈，。</li><li><a href="http://www.laruence.com/2010/06/08/1579.html#comment-2863" >2010/06/29</a>, <a href="http://sanmuding.com"  rel="external nofollow"  class="url" >Anders</a> writes: 这么简单的事情，这么大的数据量 为什么要用正则来解决呢?</li><li><a href="http://www.laruence.com/2010/06/08/1579.html#comment-3085" >2010/08/18</a>, <a href="http://www.bpzc.net/article-84.html"  rel="external nofollow"  class="url" >半瓶子醋 &raquo; [PHP]正则(pcre)最大回溯/递归限制</a> writes: [...] 转自[风雪之隅] [...]</li></ul><hr/><small  style="font-size:85%;font-size:85%;">Copyright &copy; 2010 <a href="http://www.laruence.com"  target="_blank" >风雪之隅</a> 版权所有, 转载务必注明. 该Feed只供个人使用, 禁止未注明的转载或商业应用. 非法应用的, 一切法律后果自负. 如有问题, 可发E-mail至my at laruence.com.(Digital Fingerprint: 73540ba0a1738d7d07d4b6038d5615e2)</small>]]></content:encoded>
			<wfw:commentRss>http://www.laruence.com/2010/06/08/1579.html/feed</wfw:commentRss>
		<slash:comments>19</slash:comments>
		</item>
		<item>
		<title>PHP错误抑制符(@)导致引用传参失败的Bug</title>
		<link>http://www.laruence.com/2010/05/28/1565.html</link>
		<comments>http://www.laruence.com/2010/05/28/1565.html#comments</comments>
		<pubDate>Fri, 28 May 2010 14:27:58 +0000</pubDate>
		<dc:creator>雪候鸟</dc:creator>
				<category><![CDATA[PHP应用]]></category>
		<category><![CDATA[PHP源码分析]]></category>
		<category><![CDATA[@]]></category>
		<category><![CDATA[bug]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[refer]]></category>
		<category><![CDATA[send_ref]]></category>
		<category><![CDATA[send_var_no_ref]]></category>

		<guid isPermaLink="false">http://www.laruence.com/?p=1565</guid>
		<description><![CDATA[今天cici网友发来一个问题, 说是在函数调用参数前面使用错误抑制符号(@)的时候, 貌似引用传参就失效了. 他想让我帮他解答为什么.

     看下面的例子:
<coolcode lang="php" linenum="off">
.....
</coolcode>

  这个问题, 我之前没有遇到过, 所以首先去找找相关资料, 看看有没有现成的答案, Goolge了一番, 发现虽然有人已经向PHP报了类似的Bug:<a href="http://bugs.php.net/bug.php?id=47623" target="_blank">http://bugs.php.net/bug.php?id=47623</a>, 但PHP官方还没有解决, 也没有给出答复.

   没办法, 只能自己分析了...]]></description>
			<content:encoded><![CDATA[<div class="copyright" >
<ul  style="padding-left:1em;font-size:85%;padding-left:1em;font-size:85%;">
<li>作者: laruence(<a href="http://www.laruence.com"  title="风雪之隅"  target="_blank" >http://www.laruence.com</a>)</li>
<li>本文地址: <a href="http://www.laruence.com/2010/05/28/1565.html"  title="Permanet Link to PHP错误抑制符(@)导致引用传参失败的Bug" >http://www.laruence.com/2010/05/28/1565.html</a></li>
<li>转载请注明出处 </li>
</ul></div>
<p>
     今天cici网友发来一个问题, 说是在函数调用参数前面使用错误抑制符号(@)的时候, 貌似引用传参就失效了. 他想让我帮他解答为什么.</p>
<p>     看下面的例子:</p>
<pre name="code"  class="sh_php"  linenum="off"   style="background: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:Monacobackground: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:MonacoConsolasConsolasCourierCouriermonospace;monospace;">
&lt;?php
$array = array(1,2,3);

function add (&amp;$arr) {
    $arr[] = 4;
}
add(@$array);
print_r($array);
/**
此时, $array没有改变,　输出:
Array
(
    [0] =&gt; 1
    [1] =&gt; 2
    [2] =&gt; 3
)

*/
add($array);
print_r($array);
/**
不使用错误抑制的情况下, 输出正常:
Array
(
    [0] =&gt; 1
    [1] =&gt; 2
    [2] =&gt; 3
    [3] =&gt; 4
)
*/
?&gt;
</pre>
<p>  这个问题, 我之前没有遇到过, 所以首先去找找相关资料, 看看有没有现成的答案, Goolge了一番, 发现虽然有人已经向PHP报了类似的Bug:<a href="http://bugs.php.net/bug.php?id=47623"  target="_blank" >http://bugs.php.net/bug.php?id=47623</a>, 但PHP官方还没有解决, 也没有给出答复.</p>
<p>   没办法, 只能自己分析了, 之前我曾经在文章中介绍过错误抑制符的原理(<a href="http://www.laruence.com/2009/07/27/1020.html" > 深入理解PHP原理之错误抑制与内嵌HTML</a>), 从原理上来说, 错误抑制只是修改了error_reporting的level, 按理来说不会影响到上下文之间的函数调用的机制. 只能通过实地试验了.</p>
<p>   经过gdb跟踪, 发现在使用了错误移植符以后, 函数调用前的传参opcode不同:</p>
<pre name="code"  class="sh_bash"  linenum="off"   style="background: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:Monacobackground: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:MonacoConsolasConsolasCourierCouriermonospace;monospace;">
//没有使用错误抑制符的时候
OPCODE = SEND_REF 

//使用了错误抑制符号以后
OPCODE = SEND_VAR_NO_REF
</pre>
<p>   问题初步定位了, 但是造成这种差异的原因又是什么呢?</p>
<p>   既然OPCODE不同, 那么肯定是在语法分析的阶段, 走了不同的分支了, 想到这一层, 问题也就好定位了, </p>
<p>   原来, PHP语法分析阶段, 把形如 &#8220;@&#8221;+expr的条目, 规约成了expr_without_variable, 而这种节点的意义就是没有变量的值, 也就是字面值, 我们都知道字面值是不能传递引用的(因为它不是变量), 所以, 就会导致这种差异.</p>
<p>  具体过程如下:<br/>
1.  语法分析阶段:</p>
<pre name="code"  class="sh_bash"  linenum="off"   style="background: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:Monacobackground: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:MonacoConsolasConsolasCourierCouriermonospace;monospace;">
expr_without_variable:
//...有省略
   |   '@' { zend_do_begin_silence(&amp;$1 TSRMLS_CC); }
       expr { zend_do_end_silence(&amp;$1 TSRMLS_CC); $$ = $3; }

//此处走了ZEND_SEND_VAL分支
non_empty_function_call_parameter_list:
        expr_without_variable   { ....} //错误的走了这个分支
    |   variable                {..... } //正常情况下
</pre>
<p>   所以导致在编译期间, 生成了不同的OPCODE, 也导致了问题的表象. </p>
<p>   最后, 我已经把原因在PHP的这个bug页做了说明, 有兴趣的可以去看看我的烂英语水平.  最后谢谢cici网友提供的这个有趣的问题.<script type="text/javascript"  src="http://www.laruence.com/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_php.js" ></script><script type="text/javascript"  src="http://www.laruence.com/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_bash.js" ></script><script type="text/javascript"  src="http://www.laruence.com/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_bash.js" ></script></p>
<hr/><h2>Comments</h2><ul  style="padding-left:1em;font-size:85%;padding-left:1em;font-size:85%;"><li><a href="http://www.laruence.com/2010/05/28/1565.html#comment-2695" >2010/05/29</a>, <a href="http://www.jaceju.net/blog/?p=1196"  rel="external nofollow"  class="url" >網站製作學習誌 &raquo; [Web] 連結分享</a> writes: [...] PHP錯誤抑制符(@)導致引用傳參失敗的Bug [...]</li><li><a href="http://www.laruence.com/2010/05/28/1565.html#comment-2698" >2010/06/01</a>, 小熊 writes: 长知识了，劳伦斯大叔威武</li><li><a href="http://www.laruence.com/2010/05/28/1565.html#comment-2730" >2010/06/10</a>, <a href="http://www.sjade.com"  rel="external nofollow"  class="url" >互联生活网</a> writes: 长知识了，</li><li><a href="http://www.laruence.com/2010/05/28/1565.html#comment-3010" >2010/07/30</a>, <a href="http://www.commentset.com"  rel="external nofollow"  class="url" >mahone</a> writes: 错误抑制符是这样用的？add(@$array);
不是用在函数前面的么？@add($array);
望求教</li><li><a href="http://www.laruence.com/2010/05/28/1565.html#comment-3012" >2010/07/30</a>, <a href="http://www.laruence.com"  rel="external nofollow"  class="url" >雪候鸟</a> writes: @mahone 有的时候, 我们引用一个数组的元素的时候, 这个数组元素可能不存在, 我们为了避免它notice, 就会采用 func(@$array['key']);</li><li><a href="http://www.laruence.com/2010/05/28/1565.html#comment-3013" >2010/07/30</a>, <a href="http://www.commentset.com"  rel="external nofollow"  class="url" >mahone</a> writes: @雪候鸟
这样的啊，那isset这样判断下不好么？
如果不判断穿进去，那是去函数里面判断了是吧 ？</li></ul><hr/><small  style="font-size:85%;font-size:85%;">Copyright &copy; 2010 <a href="http://www.laruence.com"  target="_blank" >风雪之隅</a> 版权所有, 转载务必注明. 该Feed只供个人使用, 禁止未注明的转载或商业应用. 非法应用的, 一切法律后果自负. 如有问题, 可发E-mail至my at laruence.com.(Digital Fingerprint: 73540ba0a1738d7d07d4b6038d5615e2)</small>]]></content:encoded>
			<wfw:commentRss>http://www.laruence.com/2010/05/28/1565.html/feed</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>PHP类型转换相关的一个Bug</title>
		<link>http://www.laruence.com/2010/05/26/1541.html</link>
		<comments>http://www.laruence.com/2010/05/26/1541.html#comments</comments>
		<pubDate>Wed, 26 May 2010 06:45:15 +0000</pubDate>
		<dc:creator>雪候鸟</dc:creator>
				<category><![CDATA[PHP应用]]></category>
		<category><![CDATA[PHP源码分析]]></category>
		<category><![CDATA[bug]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[php源码分析]]></category>
		<category><![CDATA[type cast]]></category>
		<category><![CDATA[类型转换]]></category>

		<guid isPermaLink="false">http://www.laruence.com/?p=1541</guid>
		<description><![CDATA[ PHP为了避免数字索引和数字字符串索引(注1)的混乱, 引入了zend_symtable_*系列函数, 并应用于数组中.
  
   这样一来, 数字字符串索引也就会被当作数字索引, 然而总是有一些情况, 是PHP的维护者没有想到的...

   比如, 类型转换时刻.]]></description>
			<content:encoded><![CDATA[<div class="copyright" >
<ul  style="padding-left:1em;font-size:85%;padding-left:1em;font-size:85%;">
<li>作者: laruence(<a href="http://www.laruence.com"  title="风雪之隅"  target="_blank" >http://www.laruence.com</a>)</li>
<li>本文地址: <a href="http://www.laruence.com/2010/05/26/1541.html"  title="Permanet Link to PHP类型转换相关的一个Bug" >http://www.laruence.com/2010/05/26/1541.html</a></li>
<li>转载请注明出处 </li>
</ul></div>
<p>
   PHP为了避免数字索引和数字字符串索引(注1)的混乱, 引入了zend_symtable_*系列函数, 并应用于数组中.</p>
<p>   这样一来, 数字字符串索引也就会被当作数字索引, 然而总是有一些情况, 是PHP的维护者没有想到的&#8230;</p>
<p>   比如, 类型转换时刻:</p>
<pre name="code"  class="sh_bash"  linenum="off"   style="background: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:Monacobackground: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:MonacoConsolasConsolasCourierCouriermonospace;monospace;">
鉴于很多朋友好心的提示, 使用json_deocde的第二个参数就可以直接得到数组.
我说明下, 如下的代码是我有意而为之, 并不是为了json_decode, 而是为了构造一个&quot;有问题&quot;的数组.
</pre>
<p> 在PHP5.2.*下(json version	1.2.1):</p>
<pre name="code"  class="sh_php"  linenum="off"   style="background: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:Monacobackground: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:MonacoConsolasConsolasCourierCouriermonospace;monospace;">

$data = array(
    123 =&gt; 'laruence',
);

$value = json_encode($data);
$obj   = json_decode($value);
$arr   = (array)$obj;
var_dump($arr);
</pre>
<p>   另<a href="http://syre.blogbus.com/"  target="_blank" >神仙</a>提供了如下的更简单的构造方法:</p>
<pre name="code"  class="sh_php"  linenum="off"   style="background: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:Monacobackground: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:MonacoConsolasConsolasCourierCouriermonospace;monospace;">
$obj=new stdClass;
$obj-&gt;{'123'} = &quot;laruence&quot;;
$arr = (array)$obj;
var_dump($arr);
</pre>
<p>   此时, 问题就出现了, 上面得到的输出是:</p>
<pre name="code"  class="sh_bash"  linenum="off"   style="background: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:Monacobackground: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:MonacoConsolasConsolasCourierCouriermonospace;monospace;">
array(1) {
  [&quot;123&quot;]=&gt;
  string(8) &quot;laruence&quot;
}
</pre>
<p>   现在,你郁闷吧, 因为数组键是字符串, 而通过正常渠道访问的时候, PHP都会自动把数字字符串转换成数字, 所以:</p>
<pre name="code"  class="sh_php"  linenum="off"   style="background: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:Monacobackground: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:MonacoConsolasConsolasCourierCouriermonospace;monospace;">
print_r($arr[123]);
//PHP Notice:  Undefined offset:  123 in ***
print_r($arr[&quot;123&quot;]);
//PHP Notice:  Undefined offset:  123 in ***
var_dump(array_key_exists(&quot;123&quot;, $arr));
//bool(false)
</pre>
<p>  我已经报了Bug, 不过PHP本身也不保证类型转换的一致性, 所以PHP维护者最后认为是不是Bug都无所谓了, 大家平时注意即可:<a href="http://bugs.php.net/bug.php?id=51915"  target="_blank" >http://bugs.php.net/bug.php?id=51915</a> </p>
<p><b>注1</b></p>
<p> 本文中所说的字符串数字和之前的文章<a href="http://www.laruence.com/2009/02/21/662.html"  target="_blank" >PHP字符串比较</a>中所说的numeric string有一点不同, 在zend_symtable_*系列函数中, 只会吧/^-?[^0][0-9]*$/这样的字符串认为是数字字符串. 相关核心逻辑如下:</p>
<pre name="code"  class="sh_c"  linenum="off"   style="background: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:Monacobackground: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:MonacoConsolasConsolasCourierCouriermonospace;monospace;">
#define HANDLE_NUMERIC(key, length, func) {
    register char *tmp=key;
    if (*tmp=='-') {
        tmp++;
    }
    if ((*tmp&gt;='0' &amp;&amp; *tmp&lt;='9')) do {
        char *end=key+length-1;
        long idx;
        if (*tmp++=='0' &amp;&amp; length&gt;2) {
            break;
        }
        while (tmp&lt;end) {
            if (!(*tmp&gt;='0' &amp;&amp; *tmp&lt;='9')) {
                break;
            }
            tmp++;
        }
        if (tmp==end &amp;&amp; *tmp=='0') {
            if (*key=='-') {
                idx = strtol(key, NULL, 10);
                if (idx!=LONG_MIN) {
                    return func;
                }
            } else {
                idx = strtol(key, NULL, 10);
                if (idx!=LONG_MAX) {
                    return func;
                }
            }
        }
    } while (0);
}
</pre>
<p>  <b>PS</b>:我这里只有5.2.8, 5.2.11俩个版本, 各位读者如果有其他版本的PHP, 帮忙测试下是否在你的版本下也存在这个问题. 谢谢</p>
<p>  另: 谢谢<a href="http://www.cppblog.com/qywyh"  target="_blank" >远豪</a>提供这个问题, 原问题是和Memcached相关的.<br/>
<script type="text/javascript"  src="http://www.laruence.com/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_bash.js" ></script><script type="text/javascript"  src="http://www.laruence.com/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_php.js" ></script><script type="text/javascript"  src="http://www.laruence.com/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_php.js" ></script><script type="text/javascript"  src="http://www.laruence.com/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_bash.js" ></script><script type="text/javascript"  src="http://www.laruence.com/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_php.js" ></script><script type="text/javascript"  src="http://www.laruence.com/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_c.js" ></script></p>
<hr/><h2>Comments</h2><ul  style="padding-left:1em;font-size:85%;padding-left:1em;font-size:85%;"><li><a href="http://www.laruence.com/2010/05/26/1541.html#comment-2666" >2010/05/26</a>, <a href="http://skiyo.cn"  rel="external nofollow"  class="url" >Jessica</a> writes: 鸟哥 decode的时候多价格参数 不要返回object 直接返回成数组..

$arr = json_decode($value, true)</li><li><a href="http://www.laruence.com/2010/05/26/1541.html#comment-2667" >2010/05/26</a>, <a href="http://www.laruence.com"  rel="external nofollow"  class="url" >雪候鸟</a> writes: @jessica 我是处心积虑的特意这么做的,为了构造这么个数组, 呵呵</li><li><a href="http://www.laruence.com/2010/05/26/1541.html#comment-2668" >2010/05/26</a>, <a href="http://skiyo.cn"  rel="external nofollow"  class="url" >Jessica</a> writes: 是我误会鸟哥了..汗</li><li><a href="http://www.laruence.com/2010/05/26/1541.html#comment-2669" >2010/05/26</a>, <a href="http://micy.cn/blog/"  rel="external nofollow"  class="url" >bunnyq</a> writes: 5.3.2下也是这个结果</li><li><a href="http://www.laruence.com/2010/05/26/1541.html#comment-2670" >2010/05/26</a>, .... writes: $data = array(
    123 =&gt; 'laruence',
);
var_dump($data);

这时候就打印不出来了，还需要转换么？</li><li><a href="http://www.laruence.com/2010/05/26/1541.html#comment-2671" >2010/05/26</a>, <a href="http://blog.imxifs.info"  rel="external nofollow"  class="url" >xifs</a> writes: 5.3.2也如此</li><li><a href="http://www.laruence.com/2010/05/26/1541.html#comment-2672" >2010/05/26</a>, noknow writes: 多看手册没坏处的！</li><li><a href="http://www.laruence.com/2010/05/26/1541.html#comment-2717" >2010/06/07</a>, <a href="http://syre.blogbus.com"  rel="external nofollow"  class="url" >神仙</a> writes: 有个更简单的构造办法
$obj=new stdClass;
$obj-&gt;{'123'} = 1;
$arr = (array)$obj;
var_dump($arr);</li><li><a href="http://www.laruence.com/2010/05/26/1541.html#comment-2718" >2010/06/07</a>, <a href="http://www.laruence.com"  rel="external nofollow"  class="url" >雪候鸟</a> writes: @神仙 赞, 我还真没想到能这么做. ;)</li><li><a href="http://www.laruence.com/2010/05/26/1541.html#comment-2731" >2010/06/10</a>, <a href="http://www.mmyuqi.com"  rel="external nofollow"  class="url" >两性解答</a> writes: 还需要转换么？</li><li><a href="http://www.laruence.com/2010/05/26/1541.html#comment-2848" >2010/06/26</a>, <a href="http://%/zzdwsyg1"  rel="external nofollow"  class="url" >BILLY</a> writes: <strong>PillSpot.org. Canadian Health&amp;Care.Special Internet Prices.No prescription online pharmacy.Pillspot.org.<b> <a href="http://pillspot.org/products/vitamins_herbal_supplements/ Vitamins@buy.online"  rel="nofollow" >.</a>...</strong>

Categories: <b>Stop SmokingMental HealthVitamins/Herbal Supplements.Anxiety/Sleep Aid.Antidiabetic.Eye Care.Antiviral.Antibiotics.Stomach.Blood Pressure/Heart.Antidepressants.Pain Relief.Womens Health.Anti-allergic/Asthma.Skin Care.Mens Health.Weight...</li></ul><hr/><small  style="font-size:85%;font-size:85%;">Copyright &copy; 2010 <a href="http://www.laruence.com"  target="_blank" >风雪之隅</a> 版权所有, 转载务必注明. 该Feed只供个人使用, 禁止未注明的转载或商业应用. 非法应用的, 一切法律后果自负. 如有问题, 可发E-mail至my at laruence.com.(Digital Fingerprint: 73540ba0a1738d7d07d4b6038d5615e2)</small>]]></content:encoded>
			<wfw:commentRss>http://www.laruence.com/2010/05/26/1541.html/feed</wfw:commentRss>
		<slash:comments>11</slash:comments>
		</item>
		<item>
		<title>BTwitter(Twitter In Bash)</title>
		<link>http://www.laruence.com/2010/05/24/1526.html</link>
		<comments>http://www.laruence.com/2010/05/24/1526.html#comments</comments>
		<pubDate>Mon, 24 May 2010 14:31:01 +0000</pubDate>
		<dc:creator>雪候鸟</dc:creator>
				<category><![CDATA[Linux/Unix]]></category>
		<category><![CDATA[bash]]></category>
		<category><![CDATA[btwitter]]></category>
		<category><![CDATA[Linux]]></category>

		<guid isPermaLink="false">http://www.laruence.com/?p=1526</guid>
		<description><![CDATA[    完成了第一版的bTwitter, 完美支持linux命令行下使用推特.
  
    有几点说明:
<coolcode lang="bash" linenum="off">
1. 脚本假设终端是UTF-8的, 如果不是, 请自行iconv之类的.
2. 脚本中in_reply_to, 不知何故, 不能正常在推下方显示, 谁知道为什么?
3. 新浪微薄的API地址,调用很类似, 可以方便的修改以后用到新浪微薄中.
</coolcode>
    
    下载:<a href="http://code.google.com/p/btwitter/downloads/list" target="_blank">http://code.google.com/p/btwitter/downloads/list</a>]]></description>
			<content:encoded><![CDATA[<div class="copyright" >
<ul  style="padding-left:1em;font-size:85%;padding-left:1em;font-size:85%;">
<li>作者: laruence(<a href="http://www.laruence.com"  title="风雪之隅"  target="_blank" >http://www.laruence.com</a>)</li>
<li>本文地址: <a href="http://www.laruence.com/2010/05/24/1526.html"  title="Permanet Link to BTwitter(Twitter In Bash)" >http://www.laruence.com/2010/05/24/1526.html</a></li>
<li>转载请注明出处 </li>
</ul></div>
<p>
    完成了第一版的bTwitter, 完美支持linux命令行下使用推特.</p>
<p>    有几点要说明的:</p>
<pre name="code"  class="sh_bash"  linenum="off"   style="background: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:Monacobackground: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:MonacoConsolasConsolasCourierCouriermonospace;monospace;">
1. 脚本假设终端是UTF-8的, 如果不是, 请自行iconv之类的.
2. 脚本中in_reply_to, 不知何故, 不能正常在推下方显示, 谁知道为什么?
3. 新浪微薄的API地址,调用很类似, 可以方便的修改以后用到新浪微薄中.
</pre>
<p>    现在支持:</p>
<pre name="code"  class="sh_bash"  linenum="off"   style="background: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:Monacobackground: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:MonacoConsolasConsolasCourierCouriermonospace;monospace;">
Usage：
	btwitter content    		发表Twitter
	btwitter -l|--list[USER]	查看[USER]的最新Twitter
	btwitter -f|--friend[ SIZE]	查看最新的[SIZE条]朋友更新
	btwitter -m|--mentions		查看最新的[SIZE条]@laruence
</pre>
<p>    下载:<a href="http://code.google.com/p/btwitter/downloads/list"  target="_blank" >http://code.google.com/p/btwitter/downloads/list</a></p>
<p>    展示部分参考了<a href="http://blog.dickeny.com/343.html"  target="_blank" >沈觅仁的笔记本</a>中的部分逻辑, 修复了不能显示中文, 以及sed正则的问题, 美化了输出等. </p>
<p>   使用截图:<br/>
<div id="attachment_1530"  class="wp-caption aligncenter"  style="width: 310px" ><a href="http://www.laruence.com/wp-content/uploads/metion.jpg" ><img src="http://www.laruence.com/wp-content/uploads/metion-300x49.jpg"  alt=""  title="metion"  width="300"  height="49"  class="size-medium wp-image-1530" /></a><p class="wp-caption-text" >metion</p></div><br/>
<div id="attachment_1529"  class="wp-caption aligncenter"  style="width: 310px" ><a href="http://www.laruence.com/wp-content/uploads/list.jpg" ><img src="http://www.laruence.com/wp-content/uploads/list-300x63.jpg"  alt="List"  title="list"  width="300"  height="63"  class="size-medium wp-image-1529" /></a><p class="wp-caption-text" >List</p></div></p>
<p><script type="text/javascript"  src="http://www.laruence.com/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_bash.js" ></script><script type="text/javascript"  src="http://www.laruence.com/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_bash.js" ></script></p>
<hr/><h2>Comments</h2><ul  style="padding-left:1em;font-size:85%;padding-left:1em;font-size:85%;"><li><a href="http://www.laruence.com/2010/05/24/1526.html#comment-2652" >2010/05/24</a>, <a href="http://www.laruence.com/2010/05/24/1515.html"  rel="external nofollow"  class="url" >shell下发推脚本 | 风雪之隅</a> writes: [...] 请参看最新的bTwitter. [...]</li><li><a href="http://www.laruence.com/2010/05/24/1526.html#comment-2653" >2010/05/25</a>, <a href="http://skiyo.cn"  rel="external nofollow"  class="url" >Jessica</a> writes: 汗..原来是个bush脚本..

PS 我的验证码是dan 我想后面加个疼.</li><li><a href="http://www.laruence.com/2010/05/24/1526.html#comment-2654" >2010/05/25</a>, 小熊 writes: 劳伦斯叔叔太强大了</li><li><a href="http://www.laruence.com/2010/05/24/1526.html#comment-2655" >2010/05/25</a>, <a href="http://topsy.com/trackback?utm_source=pingback&amp;utm_campaign=L2&amp;url=http://www.laruence.com/2010/05/24/1526.html"  rel="external nofollow"  class="url" >Tweets that mention BTwitter(Twitter In Bash) | 风雪之隅 -- Topsy.com</a> writes: [...] This post was mentioned on Twitter by miracle, fury, Madog, notsobad, notsobad and others. notsobad said: *****http://www.laruence.com/2010/05/24/1526.html [...]</li><li><a href="http://www.laruence.com/2010/05/24/1526.html#comment-2664" >2010/05/26</a>, <a href="http://glemir.xplore.cn"  rel="external nofollow"  class="url" >glemir</a> writes: 这个比较帅</li><li><a href="http://www.laruence.com/2010/05/24/1526.html#comment-2675" >2010/05/27</a>, evan writes: encodeURL 方法似乎有问题，不能发推，接收没问题。注释掉之后就能正常发推了</li><li><a href="http://www.laruence.com/2010/05/24/1526.html#comment-2676" >2010/05/27</a>, <a href="http://www.laruence.com"  rel="external nofollow"  class="url" >雪候鸟</a> writes: @evan 输入是UTF-8编码么?</li><li><a href="http://www.laruence.com/2010/05/24/1526.html#comment-2732" >2010/06/10</a>, <a href="http://www.xingai114.com"  rel="external nofollow"  class="url" >xingai</a> writes: 这个比较帅............</li></ul><hr/><small  style="font-size:85%;font-size:85%;">Copyright &copy; 2010 <a href="http://www.laruence.com"  target="_blank" >风雪之隅</a> 版权所有, 转载务必注明. 该Feed只供个人使用, 禁止未注明的转载或商业应用. 非法应用的, 一切法律后果自负. 如有问题, 可发E-mail至my at laruence.com.(Digital Fingerprint: 73540ba0a1738d7d07d4b6038d5615e2)</small>]]></content:encoded>
			<wfw:commentRss>http://www.laruence.com/2010/05/24/1526.html/feed</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
		<item>
		<title>shell下发推脚本</title>
		<link>http://www.laruence.com/2010/05/24/1515.html</link>
		<comments>http://www.laruence.com/2010/05/24/1515.html#comments</comments>
		<pubDate>Mon, 24 May 2010 08:08:19 +0000</pubDate>
		<dc:creator>雪候鸟</dc:creator>
				<category><![CDATA[Linux/Unix]]></category>
		<category><![CDATA[随笔]]></category>
		<category><![CDATA[bash]]></category>
		<category><![CDATA[shell]]></category>

		<guid isPermaLink="false">http://www.laruence.com/?p=1515</guid>
		<description><![CDATA[   Be Lazy, 懒得能不动鼠标, 就不愿动鼠标..

   今天在推上看到有人的下面缀着"via bash", 好奇怎么做到, 找来推的API, 其实挺简单..

   直接上代码, 不解释了, 只是有几点解释下
<coolcode lang="sh" linenum="off">
1. 如果是VPN, 不用代理, 就取消-x选项
2. 脚本直接从STDIN读取内容,内容需要是UTF-8编码, 如果你的终端不是, 那请在脚本中添加iconv
3. 做到完全脚本浏览/发推也是可以的.
4. 新浪微薄也有REST API, 理论上也是可以这么搞的.
</coolcode>]]></description>
			<content:encoded><![CDATA[<div class="copyright" >
<ul  style="padding-left:1em;font-size:85%;padding-left:1em;font-size:85%;">
<li>作者: laruence(<a href="http://www.laruence.com"  title="风雪之隅"  target="_blank" >http://www.laruence.com</a>)</li>
<li>本文地址: <a href="http://www.laruence.com/2010/05/24/1515.html"  title="Permanet Link to shell下发推脚本" >http://www.laruence.com/2010/05/24/1515.html</a></li>
<li>转载请注明出处 </li>
</ul></div>
<p>
   Be Lazy, 懒得能不动鼠标, 就不愿动鼠标..</p>
<p>   今天在推上看到有人的下面缀着&#8221;via bash&#8221;, 好奇怎么做到, 找来推的API, 其实挺简单..</p>
<p>   请参看最新的<a href="http://www.laruence.com/2010/05/24/1526.html" >bTwitter</a>.</p>
<p>   直接上代码, 不解释了, 只是有几点解释下</p>
<pre name="code"  class="sh_sh"  linenum="off"   style="background: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:Monacobackground: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:MonacoConsolasConsolasCourierCouriermonospace;monospace;">
1. 如果是VPN, 不用代理, 就取消-x选项
2. 脚本直接从STDIN读取内容,内容需要是UTF-8编码, 如果你的终端不是, 那请在脚本中添加iconv
3. 做到完全脚本浏览/发推也是可以的.
4. 新浪微薄也有REST API, 理论上也是可以这么搞的.
</pre>
<p>   代码:</p>
<pre name="code"  class="sh_sh"  linenum="off"   style="background: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:Monacobackground: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:MonacoConsolasConsolasCourierCouriermonospace;monospace;">
#!/bin/bash
#by laruence&lt;http://www.laruence.com&gt;

USERNAME=&quot;用户名&quot;
PASSWORD=&quot;密码&quot;
PROXY=&quot;代理地址&quot;

function encodeurl() {
    echo &quot;$*&quot; | awk 'BEGIN {
        split (&quot;1 2 3 4 5 6 7 8 9 A B C D E F&quot;, hextab, &quot; &quot;)
        hextab [0] = 0
        for (i=1; i&lt;=255; ++i) {
            ord [ sprintf (&quot;%c&quot;, i) &quot;&quot; ] = i + 0
        }
    }
    {
        encoded = &quot;&quot;
        for (i=1; i&lt;=length($0); ++i) {
            c = substr ($0, i, 1)
            if ( c ~ /[a-zA-Z0-9.-$]/ ) {
                encoded = encoded c             #不需要编码
            } else if ( c == &quot; &quot; ) {
                encoded = encoded &quot;+&quot;  #处理空格
            } else {
                #编码
                lo = ord [c] % 16
                hi = int (ord [c] / 16);
                encoded = encoded &quot;%&quot; hextab [hi] hextab [lo]
            }
        }
        print encoded
    }' 2&gt;/dev/null
}

URL=https://api.twitter.com/1/statuses/update.xml

CONTENT=$*
REPLY=`echo $CONTENT | sed -n -e 's/^.*@\([^ ]\+\).*$/\1/p'`

DATA=`encodeurl $CONTENT`

POST=&quot;source=bash&amp;status=$DATA&quot;

#in_reply_to老是不能在下面显示出来, 不知何故
if [ -n &quot;$REPLY&quot; ]
then
    POST=$POST&quot;&amp;in_reply_to=&quot;$REPLY
fi  

MESSAGE=`curl -3 -k --silent -x$PROXY -u$USERNAME:$PASSWORD -d&quot;$POST&quot; $URL`

exit 0
</pre>
<p><script type="text/javascript"  src="http://www.laruence.com/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_sh.js" ></script><script type="text/javascript"  src="http://www.laruence.com/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_sh.js" ></script></p>
<hr/><h2>Comments</h2><ul  style="padding-left:1em;font-size:85%;padding-left:1em;font-size:85%;"><li><a href="http://www.laruence.com/2010/05/24/1515.html#comment-2646" >2010/05/24</a>, <a href="http://www.54chen.com"  rel="external nofollow"  class="url" >54chen</a> writes: http://www.54chen.com/_linux_/ssh-twitter-client.html 分享一下perl的版本</li><li><a href="http://www.laruence.com/2010/05/24/1515.html#comment-2647" >2010/05/24</a>, <a href="http://www.laruence.com"  rel="external nofollow"  class="url" >雪候鸟</a> writes: @54chen Perl也是Linux标准配备, 顶.</li><li><a href="http://www.laruence.com/2010/05/24/1515.html#comment-2650" >2010/05/24</a>, <a href="http://pityonline.info"  rel="external nofollow"  class="url" >pityonline</a> writes: 贵博代码粘贴后每行都多了行号，还要手动去删除。最好换个能保留文件原来的编辑器……</li><li><a href="http://www.laruence.com/2010/05/24/1515.html#comment-2651" >2010/05/24</a>, Brilliance writes: 我的UTF8发出去的汉字是***= =!</li><li><a href="http://www.laruence.com/2010/05/24/1515.html#comment-2656" >2010/05/25</a>, <a href="http://topsy.com/trackback?utm_source=pingback&amp;utm_campaign=L2&amp;url=http://www.laruence.com/2010/05/24/1515.html"  rel="external nofollow"  class="url" >Tweets that mention shell下发推脚本 | 风雪之隅 -- Topsy.com</a> writes: [...] This post was mentioned on Twitter by 阿才, 大路阿神. 大路阿神 said: 【人肉GR分享】shell下发推脚本 http://www.laruence.com/2010/05/24/1515.html [...]</li><li><a href="http://www.laruence.com/2010/05/24/1515.html#comment-2891" >2010/07/08</a>, <a href="http://herrick5.com"  rel="external nofollow"  class="url" >AWu</a> writes: 靠谱！

mark了～</li><li><a href="http://www.laruence.com/2010/05/24/1515.html#comment-2892" >2010/07/08</a>, <a href="http://herrick5.com"  rel="external nofollow"  class="url" >AWu</a> writes: #in_reply_to老是不能在下面显示出来, 不知何故？

这个是什么意思？
如果是转义的话，你可以考虑用单引号～</li><li><a href="http://www.laruence.com/2010/05/24/1515.html#comment-2939" >2010/07/15</a>, <a href="http://www.laruence.com"  rel="external nofollow"  class="url" >雪候鸟</a> writes: @AWu 就是在一条twitter下面会显示 :   about * hours ago  via web  in reply to somebody</li><li><a href="http://www.laruence.com/2010/05/24/1515.html#comment-3014" >2010/07/30</a>, <a href="http://www.commentset.com"  rel="external nofollow"  class="url" >mahone</a> writes: 这样就能绕过GFW了？如果是的话请告之原理，谢谢。
还是只是一个发帖查看的简单工具？</li><li><a href="http://www.laruence.com/2010/05/24/1515.html#comment-3016" >2010/07/31</a>, <a href="http://www.laruence.com"  rel="external nofollow"  class="url" >雪候鸟</a> writes: @mahone 不会, 还需要借助代理, 或者VPN.</li></ul><hr/><small  style="font-size:85%;font-size:85%;">Copyright &copy; 2010 <a href="http://www.laruence.com"  target="_blank" >风雪之隅</a> 版权所有, 转载务必注明. 该Feed只供个人使用, 禁止未注明的转载或商业应用. 非法应用的, 一切法律后果自负. 如有问题, 可发E-mail至my at laruence.com.(Digital Fingerprint: 73540ba0a1738d7d07d4b6038d5615e2)</small>]]></content:encoded>
			<wfw:commentRss>http://www.laruence.com/2010/05/24/1515.html/feed</wfw:commentRss>
		<slash:comments>10</slash:comments>
		</item>
		<item>
		<title>Nginx + PHP CGI的一个可能的安全漏洞</title>
		<link>http://www.laruence.com/2010/05/20/1495.html</link>
		<comments>http://www.laruence.com/2010/05/20/1495.html#comments</comments>
		<pubDate>Thu, 20 May 2010 10:13:15 +0000</pubDate>
		<dc:creator>雪候鸟</dc:creator>
				<category><![CDATA[PHP应用]]></category>
		<category><![CDATA[nginx]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[php源码分析]]></category>
		<category><![CDATA[安全漏洞]]></category>

		<guid isPermaLink="false">http://www.laruence.com/?p=1495</guid>
		<description><![CDATA[现在普遍的Nginx + PHP cgi的做法是在配置文件中,　通过正则匹配(<a href="" target="_blank">Nginx(PHP/fastcgi)的PATH_INFO问题</a>)设置SCRIPT_FILENAME,  今天<a href="http://www.80sec.com/" target="_blank">小顿</a>发现了一个这种方式的安全漏洞.

   比如, 有http://www.laruence.com/fake.jpg, 那么通过构造如下的URL, 就可以看到fake.jpg的二进制内容:
<coolcode lang="bash" linenum="off">
http://www.laruence.com/fake.jpg/foo.php
</coolcode>

   为什么会这样呢?]]></description>
			<content:encoded><![CDATA[<div class="copyright" >
<ul  style="padding-left:1em;font-size:85%;padding-left:1em;font-size:85%;">
<li>作者: laruence(<a href="http://www.laruence.com"  title="风雪之隅"  target="_blank" >http://www.laruence.com</a>)</li>
<li>本文地址: <a href="http://www.laruence.com/2010/05/20/1495.html"  title="Permanet Link to Nginx + PHP CGI的一个可能的安全漏洞" >http://www.laruence.com/2010/05/20/1495.html</a></li>
<li>转载请注明出处 </li>
</ul></div>
<p>
   现在普遍的Nginx + PHP cgi的做法是在配置文件中,　通过正则匹配(<a href=""  target="_blank" >Nginx(PHP/fastcgi)的PATH_INFO问题</a>)设置SCRIPT_FILENAME,  今天<a href="http://www.80sec.com/"  target="_blank" >小顿</a>发现了一个这种方式的安全漏洞.</p>
<p>   比如, 有http://www.laruence.com/fake.jpg, 那么通过构造如下的URL, 就可以看到fake.jpg的二进制内容:</p>
<pre name="code"  class="sh_bash"  linenum="off"   style="background: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:Monacobackground: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:MonacoConsolasConsolasCourierCouriermonospace;monospace;">

http://www.laruence.com/fake.jpg/foo.php
</pre>
<p>   为什么会这样呢?</p>
<p>   比如, 如下的nginx conf:</p>
<pre name="code"  class="sh_bash"  linenum="off"   style="background: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:Monacobackground: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:MonacoConsolasConsolasCourierCouriermonospace;monospace;">
location ~ \.php($|/) {
	fastcgi_pass   127.0.0.1:9000;
	fastcgi_index  index.php;

	set $script    $uri;
	set $path_info &quot;&quot;;
	if ($uri ~ &quot;^(.+\.php)(/.*)&quot;) {
		set  $script     $1;
		set  $path_info  $2;
	}

	include       fastcgi_params;
	fastcgi_param SCRIPT_FILENAME   $document_root$script;
	fastcgi_param SCRIPT_NAME       $script;
	fastcgi_param PATH_INFO         $path_info;
}
</pre>
<p>   通过正则匹配以后, SCRIPT_NAME会被设置为&#8221;fake.jpg/foo.php&#8221;, 继而构造成SCRIPT_FILENAME传递个PHP CGI, 但是PHP又为什么会接受这样的参数, 并且把a.jpg解析呢?</p>
<p>   这就要说到PHP的cgi SAPI中的参数, fix_pathinfo了:</p>
<pre name="code"  class="sh_bash"  linenum="off"   style="background: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:Monacobackground: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:MonacoConsolasConsolasCourierCouriermonospace;monospace;">
; cgi.fix_pathinfo provides *real* PATH_INFO/PATH_TRANSLATED support for CGI.  PHP's
; previous behaviour was to set PATH_TRANSLATED to SCRIPT_FILENAME, and to not grok
; what PATH_INFO is.  For more information on PATH_INFO, see the cgi specs.  Setting
; this to 1 will cause PHP CGI to fix it's paths to conform to the spec.  A setting
; of zero causes PHP to behave as before.  Default is 1.  You should fix your scripts
; to use SCRIPT_FILENAME rather than PATH_TRANSLATED.
cgi.fix_pathinfo=1
</pre>
<p>   如果开启了这个选项, 那么就会触发在PHP中的如下逻辑:</p>
<pre name="code"  class="sh_c"  linenum="off"   style="background: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:Monacobackground: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:MonacoConsolasConsolasCourierCouriermonospace;monospace;">
/*
 * if the file doesn't exist, try to extract PATH_INFO out
 * of it by stat'ing back through the '/'
 * this fixes url's like /info.php/test
 */
if (script_path_translated &amp;&amp;
	(script_path_translated_len = strlen(script_path_translated)) &gt; 0 &amp;&amp;
	(script_path_translated[script_path_translated_len-1] == '/' ||
....//以下省略.
</pre>
<p>   到这里, PHP会认为SCRIPT_FILENAME是fake.jpg, 而foo.php是PATH_INFO, 然后PHP就把fake.jpg当作一个PHP文件来解释执行&#8230; So&#8230;</p>
<p>   这个隐患的危害用小顿的话来说, 是巨大的.</p>
<p>   对于一些论坛来说, 如果上传一个图片(实际上是恶意的PHP脚本), 继而构造这样的访问请求&#8230;</p>
<p>   所以, 大家如果有用这种服务器搭配的, 请排查, 如果有隐患, <b>请关闭fix_pathinfo(默认是开启的)</b>. </p>
<p>   详细漏洞信息, 请移步小顿的BLOG: <a href="http://www.80sec.com/nginx-securit.html"  target="_blank" >80Sec</a></p>
<p>   <b>另: 我认为这个和Nginx没啥关系, 不属于Nginx的漏洞. 是配置的问题, 现在到处都在说是Nginx的Bug, 不妥不妥.</b><br/>
<script type="text/javascript"  src="http://www.laruence.com/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_bash.js" ></script><script type="text/javascript"  src="http://www.laruence.com/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_bash.js" ></script><script type="text/javascript"  src="http://www.laruence.com/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_bash.js" ></script><script type="text/javascript"  src="http://www.laruence.com/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_c.js" ></script></p>
<hr/><h2>Comments</h2><ul  style="padding-left:1em;font-size:85%;padding-left:1em;font-size:85%;"><li><a href="http://www.laruence.com/2010/05/20/1495.html#comment-2592" >2010/05/20</a>, <a href="http://www.54chen.com/php-tech/nginx-php-cgi-of-security-hole.html"  rel="external nofollow"  class="url" >[警示]Nginx + PHP CGI的安全漏洞：fix_pathinfo - 五四陈科学院-坚信科学,分享技术</a> writes: [...] 临近下班，见到鸟哥的一则php漏洞说明，具体说明在 http://www.laruence.com/2010/05/20/1495.html [...]</li><li><a href="http://www.laruence.com/2010/05/20/1495.html#comment-2593" >2010/05/20</a>, <a href="http://topsy.com/trackback?utm_source=pingback&amp;utm_campaign=L2&amp;url=http://www.laruence.com/2010/05/20/1495.html"  rel="external nofollow"  class="url" >Tweets that mention Nginx + PHP CGI的一个可能的安全漏洞 | 风雪之隅 -- Topsy.com</a> writes: [...] This post was mentioned on Twitter by blogkid, 姚东旭, lqik2004, fantasy, Laruence and others. Laruence said: 请转发, 这个漏洞的影响范围挺大:Nginx + PHP CGI的一个可能的安全漏洞 , http://www.laruence.com/2010/05/20/1495.html [...]</li><li><a href="http://www.laruence.com/2010/05/20/1495.html#comment-2594" >2010/05/20</a>, <a href="http://www.rddqi.com/"  rel="external nofollow"  class="url" >王经</a> writes: 好呀</li><li><a href="http://www.laruence.com/2010/05/20/1495.html#comment-2595" >2010/05/20</a>, <a href="http://nod32.5151shop.com/?p=624"  rel="external nofollow"  class="url" >nod32升级id &raquo; nginx文件类型错误解析漏洞</a> writes: [...] 鸣谢laruence大牛在分析过程中给的帮助 No tags for this [...]</li><li><a href="http://www.laruence.com/2010/05/20/1495.html#comment-2598" >2010/05/20</a>, <a href="http://jackywdx.cn/2010/05/path_info_in_php/"  rel="external nofollow"  class="url" >PHP中的PATH_INFO | 鸭嘴的blog</a> writes: [...] PHP中的PATH_INFO 2010-05-20 14:00:22 | PHP  一直没有理解$_SERVER[&#39;PATH_INFO&#39;]这个变量的意义，今天看了风雪之隅的一篇文章Nginx + PHP CGI的一个可能的安全漏洞之后才关注一下这个变量。 [...]</li><li><a href="http://www.laruence.com/2010/05/20/1495.html#comment-2600" >2010/05/20</a>, <a href="http://www.laruence.com"  rel="external nofollow"  class="url" >雪候鸟</a> writes: 当当网发现此安全漏洞, 有谁认识当当的人么? 转发下, 让他们赶紧修复吧, 谢谢</li><li><a href="http://www.laruence.com/2010/05/20/1495.html#comment-2602" >2010/05/21</a>, <a href="http://www.sgjblog.com/archives/55"  rel="external nofollow"  class="url" >nginx文件类型错误解析漏洞 | 失光 記。 | 当 雙眼 都失去光芒 你还想留念什么?|it新闻|it咨询|it博客门户|我们都在IT|软件资讯|绿色软件|失光软件</a> writes: [...] PS: 鸣谢laruence大牛在分析过程中给的帮助 [...]</li><li><a href="http://www.laruence.com/2010/05/20/1495.html#comment-2603" >2010/05/21</a>, <a href="http://www.zoeey.com/"  rel="external nofollow"  class="url" >MoXie</a> writes: 这让我想起Apache中FilesMatch的漏洞。
FilesMatch "\.php"
结果造成文件名中只要包含.php就当Php执行了。
FilesMatch "\.php$" 这样才正确。</li><li><a href="http://www.laruence.com/2010/05/20/1495.html#comment-2604" >2010/05/21</a>, <a href="http://scotoma.cnblogs.com"  rel="external nofollow"  class="url" >scotoma</a> writes: 谢谢...这个转发到Nginx群里面的了,提醒各位SA修改下配置文件,确实有很大的危害.
感谢博主</li><li><a href="http://www.laruence.com/2010/05/20/1495.html#comment-2605" >2010/05/21</a>, <a href="http://icodex.org/2010/05/nginx%e6%96%87%e4%bb%b6%e7%b1%bb%e5%9e%8b%e9%94%99%e8%af%af%e8%a7%a3%e6%9e%90%e6%bc%8f%e6%b4%9e/"  rel="external nofollow"  class="url" >nginx文件类型错误解析漏洞</a> writes: [...]  或者  if ( $fastcgi_script_name ~ ..*/.*php ) { return 403; } PS: 鸣谢laruence大 牛在分析过程中给的帮助转载自: [...]</li><li><a href="http://www.laruence.com/2010/05/20/1495.html#comment-2606" >2010/05/21</a>, <a href="http://sanmuding.com"  rel="external nofollow"  class="url" >Anders</a> writes: 其实，从这个常见的 nginx 配置上看，是有问题的，最好还是严格一些的好。。

#      if ($uri ~ "^(\w+\.php)(/.*)") {
#           set $script $1;
#           set $path_info $2;
#      }</li><li><a href="http://www.laruence.com/2010/05/20/1495.html#comment-2607" >2010/05/21</a>, <a href="http://www.xtgly.com/2010/05/21/nginx%e6%96%87%e4%bb%b6%e7%b1%bb%e5%9e%8b%e9%94%99%e8%af%af%e8%a7%a3%e6%9e%90%e6%bc%8f%e6%b4%9e.htm"  rel="external nofollow"  class="url" >SystemAdmin Blog &raquo; Blog Archive &raquo; nginx文件类型错误解析漏洞</a> writes: [...] 鸣谢laruence大牛在分析过程中给的帮助 [...]</li><li><a href="http://www.laruence.com/2010/05/20/1495.html#comment-2608" >2010/05/21</a>, <a href="http://www.vpser.net/manage/nginx-securit-script_filename.html"  rel="external nofollow"  class="url" >nginx文件类型错误解析漏洞 - VPS侦探</a> writes: [...]  或者  if ( $fastcgi_script_name ~ ..*/.*php ) { return 403; } PS: 鸣谢laruence大 [...]</li><li><a href="http://www.laruence.com/2010/05/20/1495.html#comment-2609" >2010/05/21</a>, <a href="http://www.iamle.com/archives/602.html"  rel="external nofollow"  class="url" >nginx紧急漏洞修复！nginx文件类型错误解析漏洞 | 流水理鱼|wwek</a> writes: [...] PS: 鸣谢laruence大牛在分析过程中给的帮助 [...]</li><li><a href="http://www.laruence.com/2010/05/20/1495.html#comment-2611" >2010/05/21</a>, <a href="http://blog.nekonokoya.cn/?p=150"  rel="external nofollow"  class="url" >猫の小屋 &raquo; Blog Archive &raquo; nginx文件类型错误解析漏洞</a> writes: [...] 鸣谢laruence大 [...]</li><li><a href="http://www.laruence.com/2010/05/20/1495.html#comment-2612" >2010/05/21</a>, <a href="http://blog.zhoubing.org/10252.html"  rel="external nofollow"  class="url" >nginx文件类型错误解析漏洞 &laquo; zhoubing&#39;s blog</a> writes: [...] PS: 鸣谢laruence大牛在分析过程中给的帮助 [...]</li><li><a href="http://www.laruence.com/2010/05/20/1495.html#comment-2613" >2010/05/21</a>, <a href="http://www.g78.net/index.php/nginx_securit"  rel="external nofollow"  class="url" >收藏一点 &raquo; nginx文件类型错误解析漏洞</a> writes: [...] PS: 鸣谢laruence大牛在分析过程中给的帮助 [...]</li><li><a href="http://www.laruence.com/2010/05/20/1495.html#comment-2614" >2010/05/21</a>, <a href="http://blog.7xiaowu.cn/2010/05/21/1145.html"  rel="external nofollow"  class="url" >[转]nginx文件类型错误解析漏洞 | 游侠海外岛</a> writes: [...] 鸣谢laruence大 [...]</li><li><a href="http://www.laruence.com/2010/05/20/1495.html#comment-2615" >2010/05/21</a>, <a href="http://www.shocr.com/nginx-securit-filetype/"  rel="external nofollow"  class="url" >nginx文件类型错误解析漏洞 - Blinux</a> writes: [...] jQuery(document).ready(function($){if(navigator.platform==&quot;iPad&quot;)return;jQuery(&quot;img&quot;).lazyload({effect:&quot;fadeIn&quot;,placeholder:&quot;http://www.shocr.com/wp-content/plugins/jquery-image-lazy-loading/images/grey.gif&quot;});});Blinux首页在线手册手机访问订阅RSS关于Englishnginx文件类型错误解析漏洞 Blinux Post in Linux的大杂烩，Tags: nginx, 安全 21 五月 2010 0 google_ad_client=&quot;pub-0521178536912504&quot;;google_ad_slot=&quot;8160586556&quot;;google_ad_width=468;google_ad_height=60; 热烈欢迎您来到Blinux!强烈推荐你订阅本博客 猛击此链接 .漏洞介绍：nginx是一款高性能的web服务器，使用非常广泛，其不仅经常被用作反向代理，也可以非常好的支持PHP的运行。80sec发现其中存在一个较为严重的安全问题，默认情况下可能导致服务器错误的将任何类型的文件以PHP的方式进行解析，这将导致严重的安全问题，使得恶意的攻击者可能攻陷支持php的nginx服务器。漏洞分析：nginx默认以cgi的方式支持php的运行，譬如在配置文件当中可以以location ~ .php$ { root html; fastcgi_pass 127.0.0.1:9000; fastcgi_index index.php; fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name; include fastcgi_params; }的方式支持对php的解析，location对请求进行选择的时候会使用URI环境变量进行选择，其中传递到后端Fastcgi的关键变量SCRIPT_FILENAME由nginx生成的$fastcgi_script_name决定，而通过分析可以看到$fastcgi_script_name是直接由URI环境变量控制的，这里就是产生问题的点。而为了较好的支持PATH_INFO的提取，在PHP的配置选项里存在cgi.fix_pathinfo选项，其目的是为了从SCRIPT_FILENAME里取出真正的脚本名。 那么假设存在一个http://www.80sec.com/80sec.jpg，我们以如下的方式去访问http://www.80sec.com/80sec.jpg/80sec.php将会得到一个URI/80sec.jpg/80sec.php经过location指令，该请求将会交给后端的fastcgi处理，nginx为其设置环境变量SCRIPT_FILENAME，内容为/scripts/80sec.jpg/80sec.php而在其他的webserver如lighttpd当中，我们发现其中的SCRIPT_FILENAME被正确的设置为/scripts/80sec.jpg所以不存在此问题。 后端的fastcgi在接受到该选项时，会根据fix_pathinfo配置决定是否对SCRIPT_FILENAME进行额外的处理，一般情况下如果不对fix_pathinfo进行设置将影响使用PATH_INFO进行路由选择的应用，所以该选项一般配置开启。Php通过该选项之后将查找其中真正的脚本文件名字，查找的方式也是查看文件是否存在，这个时候将分离出SCRIPT_FILENAME和PATH_INFO分别为/scripts/80sec.jpg和80sec.php最后，以/scripts/80sec.jpg作为此次请求需要执行的脚本，攻击者就可以实现让nginx以php来解析任何类型的文件了。POC： 访问一个nginx来支持php的站点，在一个任何资源的文件如robots.txt后面加上/80sec.php，这个时候你可以看到如下的区别：访问http://www.80sec.com/robots.txtHTTP/1.1 200 OK Server: nginx/0.6.32 Date: Thu, 20 May 2010 10:05:30 GMT Content-Type: text/plain Content-Length: 18 Last-Modified: Thu, 20 May 2010 06:26:34 GMT Connection: keep-alive Keep-Alive: timeout=20 Accept-Ranges: bytes访问访问http://www.80sec.com/robots.txt/80sec.phpHTTP/1.1 200 OK Server: nginx/0.6.32 Date: Thu, 20 May 2010 10:06:49 GMT Content-Type: text/html Transfer-Encoding: chunked Connection: keep-alive Keep-Alive: timeout=20 X-Powered-By: PHP/5.2.6其中的Content-Type的变化说明了后端负责解析的变化，该站点就可能存在漏洞。漏洞厂商：http://www.nginx.org解决方案：我们已经尝试联系官方，但是此前你可以通过以下的方式来减少损失关闭cgi.fix_pathinfo为0或者if ( $fastcgi_script_name ~ ..*/.*php ) { return 403; }PS: 鸣谢laruence大牛在分析过程中给的帮助nginx文件类型错误解析漏洞:http://www.80sec.com/nginx-securit.html原创文章，转载请注明： 转载自Blinux本文链接地址: nginx文件类型错误解析漏洞No input file specified. (2)php安全设置之open_basedir (0)nginx windows发行已久 (0)nginx 301重定向 (4)给网站根目录添加sgid权限 (7)关闭Linux服务器ping响应 (0)nginx 自定义404 500 502 错误页面 (0)nginx 重启命令 (0)nginx 虚拟主机 (0) &laquo; Prev：SSH证书让Putty免密码登陆Linux Leave a Reply Name  Mail (will not be published)  Website [...]</li><li><a href="http://www.laruence.com/2010/05/20/1495.html#comment-2616" >2010/05/21</a>, <a href="http://blog.licess.org/nginx-securit-script_filename/"  rel="external nofollow"  class="url" >nginx文件类型错误解析漏洞 - Licess&#39;s Blog</a> writes: [...] 鸣谢laruence大 [...]</li><li><a href="http://www.laruence.com/2010/05/20/1495.html#comment-2617" >2010/05/21</a>, <a href="http://www.vpslab.cn/104"  rel="external nofollow"  class="url" >nginx文件类型错误解析漏洞 @ VPS实验室</a> writes: [...] 鸣谢laruence大 [...]</li><li><a href="http://www.laruence.com/2010/05/20/1495.html#comment-2618" >2010/05/21</a>, <a href="http://phprimer.com"  rel="external nofollow"  class="url" >Neaton</a> writes: 应该跟php-fpm的版本有关系，0.6以下除0.6以外的版本才受这个漏洞的影响，可以测试下。</li><li><a href="http://www.laruence.com/2010/05/20/1495.html#comment-2619" >2010/05/21</a>, <a href="http://www.shusheng.tk/index.php/archives/83"  rel="external nofollow"  class="url" >nginx文件类型错误解析漏洞 - 书生博客</a> writes: [...] 鸣谢laruence大牛在分析过程中给的帮助    上一篇:  帝国网站管理系统之自定义系统模型 [...]</li><li><a href="http://www.laruence.com/2010/05/20/1495.html#comment-2620" >2010/05/21</a>, <a href="http://blog.guangla.com/nginx%e6%9a%b4%e5%ae%89%e5%85%a8%e6%bc%8f%e6%b4%9e%ef%bc%8c%e5%af%bc%e8%87%b4%e6%9c%8d%e5%8a%a1%e5%99%a8%e8%a2%ab%e6%8f%90%e6%9d%83/"  rel="external nofollow"  class="url" >Nginx暴安全漏洞，导致服务器被提权</a> writes: [...] 鸣谢laruence大 牛在分析过程中给的帮助    &nbsp;     0 评论   Leave A [...]</li><li><a href="http://www.laruence.com/2010/05/20/1495.html#comment-2621" >2010/05/21</a>, <a href="http://www.mmyuqi.com"  rel="external nofollow"  class="url" >两性解答</a> writes: <a href="http://www.mmyuqi.com/"  rel="nofollow" >两性解答</a>关注一下</li><li><a href="http://www.laruence.com/2010/05/20/1495.html#comment-2623" >2010/05/21</a>, <a href="http://key0.cn/index.php/archives/730"  rel="external nofollow"  class="url" >nginx文件类型错误解析漏洞 &#8211; kindle&#39;s blog</a> writes: [...] 鸣谢laruence大 牛在分析过程中给的帮助    Posted on 2010-05-21 at 3:05 下午 | Filed: 网络文摘 | [...]</li><li><a href="http://www.laruence.com/2010/05/20/1495.html#comment-2624" >2010/05/21</a>, <a href="http://www.shotki.com/hezll/2010/05/nginxphp-80sec-0day%e6%bc%8f%e6%b4%9e%e8%af%a6%e7%bb%86%e5%88%86%e6%9e%90%ef%bc%9afix_pathinfo/"  rel="external nofollow"  class="url" >Nginx/PHP 80sec 0day漏洞详细分析：fix_pathinfo &laquo; Hezll 博客</a> writes: [...] http://www.laruence.com/2010/05/20/1495.html [...]</li><li><a href="http://www.laruence.com/2010/05/20/1495.html#comment-2628" >2010/05/21</a>, Bingo writes: http://wiki.nginx.org/NginxHttpFcgiModule#fastcgi_split_path_info

图片上传的路径加上这个配置可能就可以了
location ~ ^(.+\.jpe?g)(.*)$ {
...
fastcgi_split_path_info ^(.+\.jpe?g)(.*)$;
fastcgi_param SCRIPT_FILENAME /path/to/php$fastcgi_script_name;
fastcgi_param PATH_INFO $fastcgi_path_info;
fastcgi_param PATH_TRANSLATED $document_root$fastcgi_path_info;
...
}</li><li><a href="http://www.laruence.com/2010/05/20/1495.html#comment-2630" >2010/05/21</a>, <a href="http://aggron.org/archives/nginx-fcgi-php-scriptname-bug.html"  rel="external nofollow"  class="url" >Aggron的博客 &raquo; nginx php cgi漏洞</a> writes: [...] 从http://www.laruence.com/2010/05/20/1495.html看到的：nginx+fcgi+php可能会存在一个很严重的安全漏洞。使用nginx + fcgi跑PHP的童鞋注意了，据说已经有网站中招。 [...]</li><li><a href="http://www.laruence.com/2010/05/20/1495.html#comment-2632" >2010/05/21</a>, <a href="http://www.0xf3sec.org/nginx%e6%96%87%e4%bb%b6%e7%b1%bb%e5%9e%8b%e9%94%99%e8%af%af%e8%a7%a3%e6%9e%90%e6%bc%8f%e6%b4%9e/"  rel="external nofollow"  class="url" >nginx文件类型错误解析漏洞 | 0xf3sec&#39;blog</a> writes: [...] 鸣谢laruence大牛在分析过程中给的帮助  [...]</li><li><a href="http://www.laruence.com/2010/05/20/1495.html#comment-2633" >2010/05/21</a>, <a href="http://www.akang.info/?p=462"  rel="external nofollow"  class="url" >IIS漏洞和nginx漏洞同时爆出，你的网站被爆了吗？ - 阿伉守候</a> writes: [...] 鸣谢laruence大牛在分析过程中给的帮助  [...]</li><li><a href="http://www.laruence.com/2010/05/20/1495.html#comment-2635" >2010/05/22</a>, <a href="http://www.ershao.net/archives/280.html"  rel="external nofollow"  class="url" >nginx文件类型错误解析漏洞 - 二少&#39;s Blog</a> writes: [...] 鸣谢laruence大牛在分析过程中给的帮助 评论（0） [...]</li><li><a href="http://www.laruence.com/2010/05/20/1495.html#comment-2636" >2010/05/22</a>, <a href="http://www.miao.la/2010/05/nginx-exp-and-%e6%bc%8f%e6%b4%9e%e6%89%ab%e6%8f%8f%e5%99%a8/"  rel="external nofollow"  class="url" >MIAO&#39;BLOG &raquo; Blog Archive &raquo; nginx exp and 漏洞扫描器</a> writes: [...] 延伸阅读：laruence [...]</li><li><a href="http://www.laruence.com/2010/05/20/1495.html#comment-2637" >2010/05/22</a>, <a href="http://www.linuxzj.com/nginx/nginx-securit.html"  rel="external nofollow"  class="url" >nginx文件类型错误解析漏洞 | Linux之家</a> writes: [...] PS: 鸣谢laruence大牛在分析过程中给的帮助 [...]</li><li><a href="http://www.laruence.com/2010/05/20/1495.html#comment-2638" >2010/05/22</a>, <a href="http://www.phpvim.net/php/security-risks-caused-by-fix-pathinfo.html"  rel="external nofollow"  class="url" >Verdana DevNotes &raquo; PHP CGI 中 fix_pathinfo 引起的安全隐患</a> writes: [...] 关于这个问题，已有高手 laruence 做过详细的分析，这里再多啰嗦几句。 [...]</li><li><a href="http://www.laruence.com/2010/05/20/1495.html#comment-2639" >2010/05/23</a>, <a href="http://www.xslife.net/?p=313"  rel="external nofollow"  class="url" >nginx文件类型错误解析漏洞&#8211;（转） | 品味人生，享受生活</a> writes: [...] 鸣谢laruence大牛在分析过程中给的帮助   转自：80sec.com [...]</li><li><a href="http://www.laruence.com/2010/05/20/1495.html#comment-2640" >2010/05/23</a>, <a href="http://www.xxc.com"  rel="external nofollow"  class="url" >Free</a> writes: This is ......(T)</li><li><a href="http://www.laruence.com/2010/05/20/1495.html#comment-2642" >2010/05/23</a>, <a href="http://blog.sudu.us/linux/nginx-securit-script.html"  rel="external nofollow"  class="url" >nginx文件类型错误解析漏洞 | Sudu&#39;s Blog</a> writes: [...] ( $fastcgi_script_name ~ ..*/.*php ) { return 403; }  PS: 鸣谢laruence大 牛在分析过程中给的帮助转载自：http://www.80sec.com/nginx-securit.html日志信息 [...]</li><li><a href="http://www.laruence.com/2010/05/20/1495.html#comment-2643" >2010/05/24</a>, <a href="http://www.js4j.com"  rel="external nofollow"  class="url" >技术门户网站</a> writes: 好专业，不过很久没更新啦</li><li><a href="http://www.laruence.com/2010/05/20/1495.html#comment-2644" >2010/05/24</a>, <a href="http://www.joey.ws/%e5%b9%bf%e8%80%8c%e5%91%8a%e4%b9%8b/nginx%e5%8f%91%e7%8e%b0%e9%87%8d%e5%a4%a7%e6%bc%8f%e6%b4%9e/"  rel="external nofollow"  class="url" >Nginx发现重大漏洞 | 袋鼠空间 - Just One Eximious Yelling! 超凡者的呐喊！</a> writes: [...] 鸣谢laruence大 [...]</li><li><a href="http://www.laruence.com/2010/05/20/1495.html#comment-2645" >2010/05/24</a>, <a href="http://blog.unicoicn.com/2010/05/nginx%e6%96%87%e4%bb%b6%e7%b1%bb%e5%9e%8b%e9%94%99%e8%af%af%e8%a7%a3%e6%9e%90%e6%bc%8f%e6%b4%9e.html"  rel="external nofollow"  class="url" >乾亨网络工作室 &raquo; Blog Archive &raquo; nginx文件类型错误解析漏洞</a> writes: [...]  或者  if ( $fastcgi_script_name ~ ..*/.*php ) { return 403; } PS: 鸣谢laruence大牛在分析过程中给的帮助No related posts.以上关联文章由 Yet Another Related Posts [...]</li><li><a href="http://www.laruence.com/2010/05/20/1495.html#comment-2649" >2010/05/24</a>, <a href="http://www.xujun.org/?p=156"  rel="external nofollow"  class="url" >junjun的世界 &raquo; nginx文件类型错误解析漏洞</a> writes: [...] 鸣谢laruence大牛在分析过程中给的帮助    发表评论 | Trackback        [...]</li><li><a href="http://www.laruence.com/2010/05/20/1495.html#comment-2674" >2010/05/26</a>, <a href="http://www.afeiblog.com.cn/index.php/archives/281"  rel="external nofollow"  class="url" >阿飞的博客 &raquo; nginx文件类型错误解析漏洞</a> writes: [...] 鸣谢laruence大牛在分析过程中给的帮助 [...]</li><li><a href="http://www.laruence.com/2010/05/20/1495.html#comment-2697" >2010/05/31</a>, <a href="http://www.07mi.com/vps-optimization-setup/nginx-oday-80sec/"  rel="external nofollow"  class="url" >齐米优惠吧 &raquo; Blog Archive &raquo; nginx文件类型错误解析漏洞</a> writes: [...] 鸣谢laruence大牛在分析过程中给的帮助  转载自：http://www.80sec.com/nginx-securit.html    Don&#39;t [...]</li><li><a href="http://www.laruence.com/2010/05/20/1495.html#comment-2700" >2010/06/01</a>, <a href="http://www.imiyoo.com/blog/?p=19"  rel="external nofollow"  class="url" >nginx文件类型错误解析漏洞 | i-Mi-Yoo</a> writes: [...] PS: 鸣谢laruence大牛在分析过程中给的帮助 [...]</li><li><a href="http://www.laruence.com/2010/05/20/1495.html#comment-2721" >2010/06/09</a>, <a href="http://oblog.weilaijieshi.com/?p=10"  rel="external nofollow"  class="url" >nginx文件类型错误解析漏洞 &laquo; 莫忘雪</a> writes: [...] 鸣谢laruence大牛在分析过程中给的帮助  评论（0） [...]</li><li><a href="http://www.laruence.com/2010/05/20/1495.html#comment-2727" >2010/06/09</a>, <a href="http://www.phpiis.com/archives/27"  rel="external nofollow"  class="url" >PHPiis-坏孩子的天空 &raquo; Blog Archive &raquo; nginx文件类型错误解析漏洞</a> writes: [...] 鸣谢laruence大牛在分析过程中给的帮助  [...]</li><li><a href="http://www.laruence.com/2010/05/20/1495.html#comment-2729" >2010/06/10</a>, <a href="http://www.dt1x.com"  rel="external nofollow"  class="url" >打听1下</a> writes: 很严重的安全漏洞。</li><li><a href="http://www.laruence.com/2010/05/20/1495.html#comment-2769" >2010/06/21</a>, <a href="http://www.bander.com.cn"  rel="external nofollow"  class="url" >Bander</a> writes: 弱弱问一句：关闭cgi.fix_pathinfo为0 可否解决噢？</li><li><a href="http://www.laruence.com/2010/05/20/1495.html#comment-2974" >2010/07/23</a>, <a href="http://faker.iblogger.org/2010/07/nginx%e6%96%87%e4%bb%b6%e7%b1%bb%e5%9e%8b%e9%94%99%e8%af%af%e8%a7%a3%e6%9e%90%e6%bc%8f%e6%b4%9e/"  rel="external nofollow"  class="url" >nginx文件类型错误解析漏洞 | 会跳舞的鞋子</a> writes: [...] 鸣谢laruence大牛在分析过程中给的帮助       这篇日志发表于 Jul 22nd, 2010 08:31 于分类 [...]</li><li><a href="http://www.laruence.com/2010/05/20/1495.html#comment-2992" >2010/07/27</a>, <a href="http://www.bestfinance-blog.com"  rel="external nofollow"  class="url" >SerranoMaritza33</a> writes: Following my own exploration, thousands of persons on our planet receive the <a href="http://bestfinance-blog.com/topics/personal-loans"  rel="nofollow" >personal loans</a> from good banks. Therefore, there's great possibilities to receive a car loan in all countries.</li><li><a href="http://www.laruence.com/2010/05/20/1495.html#comment-3064" >2010/08/06</a>, <a href="http://www.lampblog.cn/?p=33"  rel="external nofollow"  class="url" >Trail&#39;s Blog &raquo; Nginx(PHP/fastcgi)的PATH_INFO问题</a> writes: [...] 最近发现的一个安全漏洞(Nginx + PHP CGI的一个可能的安全漏洞)和这个配置有关系, 请大家务必在使用第二种配置的时候,关闭cgi.fix_pathinfo. [...]</li></ul><hr/><small  style="font-size:85%;font-size:85%;">Copyright &copy; 2010 <a href="http://www.laruence.com"  target="_blank" >风雪之隅</a> 版权所有, 转载务必注明. 该Feed只供个人使用, 禁止未注明的转载或商业应用. 非法应用的, 一切法律后果自负. 如有问题, 可发E-mail至my at laruence.com.(Digital Fingerprint: 73540ba0a1738d7d07d4b6038d5615e2)</small>]]></content:encoded>
			<wfw:commentRss>http://www.laruence.com/2010/05/20/1495.html/feed</wfw:commentRss>
		<slash:comments>52</slash:comments>
		</item>
		<item>
		<title>深入理解PHP原理之对象(一)</title>
		<link>http://www.laruence.com/2010/05/18/1482.html</link>
		<comments>http://www.laruence.com/2010/05/18/1482.html#comments</comments>
		<pubDate>Tue, 18 May 2010 05:10:45 +0000</pubDate>
		<dc:creator>雪候鸟</dc:creator>
				<category><![CDATA[PHP源码分析]]></category>
		<category><![CDATA[object]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[php源码分析]]></category>
		<category><![CDATA[原理]]></category>

		<guid isPermaLink="false">http://www.laruence.com/?p=1482</guid>
		<description><![CDATA[<p>
	在PHP4以前, PHP并不支持面向对象, 到PHP4的时候, PHP引入了一些OOP的关键字, 请注意我用的"关键字", 因为在PHP4中的对象, 不过就是一个数组(属性)加上一个函数数组(方法), 没有访问权限控制, 没有析构函数(当然可以<a href="http://www.laruence.com/2008/09/04/498.html">模拟</a>), 等等.

	到PHP5以后, 随着Zend Engine 2的发布:
<coolcode lang="bash" lienum="off">
1. 访问权限控制
2. 接口的引入
3. 魔术方法(PHP4中可以通过overload来有限模拟) 
4. 接口的应用
5. 内置接口
等等.
</coolcode>
    PHP5终于可以算是较完美的支持面向对象了.

    而这些看似复杂的实现, 在根本上, 还是没有脱离属性数组+方法数组的基本, 接下来我就为大家揭开隐藏在源代码中的秘密.]]></description>
			<content:encoded><![CDATA[<div class="copyright" >
<ul  style="padding-left:1em;font-size:85%;padding-left:1em;font-size:85%;">
<li>作者: laruence(<a href="http://www.laruence.com"  title="风雪之隅"  target="_blank" >http://www.laruence.com</a>)</li>
<li>本文地址: <a href="http://www.laruence.com/2010/05/18/1482.html"  title="Permanet Link to 深入理解PHP原理之对象(一)" >http://www.laruence.com/2010/05/18/1482.html</a></li>
<li>转载请注明出处 </li>
</ul></div>
<p>
	在PHP4以前, PHP并不支持面向对象, 到PHP4的时候, PHP引入了一些OOP的关键字, 请注意我用的&#8221;关键字&#8221;, 因为在PHP4中的对象, 不过就是一个数组(属性)加上一个函数数组(方法), 没有访问权限控制, 没有析构函数(当然可以<a href="http://www.laruence.com/2008/09/04/498.html" >模拟</a>), 等等.</p>
<p>	到PHP5以后, 随着Zend Engine 2的发布:</p>
<pre name="code"  class="sh_bash"  linenum="off"   style="background: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:Monacobackground: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:MonacoConsolasConsolasCourierCouriermonospace;monospace;">
1. 访问权限控制
2. 接口的引入
3. 魔术方法(PHP4中可以通过overload来有限模拟)
4. 接口的应用
5. 内置接口
等等.
</pre>
<p>    PHP5终于可以算是较完美的支持面向对象了.</p>
<p>    而这些看似复杂的实现, 在根本上, 还是没有脱离属性数组+方法数组的基本, 接下来我就为大家揭开隐藏在源代码中的秘密.</p>
<p>   <b>对象的结构</b></p>
<p>   在PHP5中, 一个对象, 还是以一个zval做为载体的, 还记得什么是Zval么(<a href="http://www.laruence.com/2008/08/22/412.html"  target="_blank" >深入理解PHP原理之变量</a>).</p>
<pre name="code"  class="sh_c"  linenum="off"   style="background: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:Monacobackground: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:MonacoConsolasConsolasCourierCouriermonospace;monospace;">
typedef union _zvalue_value {
    long lval;
    double dval;
    struct {
        char *val;
        int len;
    } str;
    HashTable *ht;
    zend_object_value obj;
} zvalue_value;
</pre>
<p>	如果, 一个zval是对象, 那么zvalue_value中的obj, 就指向一个zend_object_value的实例.</p>
<p>	一个zend_object_value包含俩个成员, 一个是标识符(整形序号), 表明了当前对象存储在全局对象列表的位置, 另外还有一个zend_object_handlers指针, 指向当前对象所属类的handlers(标准操作集合).</p>
<p>	真正的对象实体, zend_object中, 保存了如下的关键信息入口:</p>
<pre name="code"  class="sh_bash"  linenum="off"   style="background: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:Monacobackground: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:MonacoConsolasConsolasCourierCouriermonospace;monospace;">
1. ce, zend_class_entry 类入口
2. properties, hashTable 普通属性集
</pre>
<p>   <b>对象的属性</b></p>
<p>	如上所述, 普通属性是一个的hashTable, 在PHP5以后, 引入了访问权限控制, 而访问权限属性, 是通过属性名进行区分的(为此Zend引入了zend_mangle_property_name).</p>
<pre name="code"  class="sh_bash"  linenum="off"   style="background: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:Monacobackground: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:MonacoConsolasConsolasCourierCouriermonospace;monospace;">
1. public  属性名
2. private \0类名\0属性名
3. protected \0*\0属性名
</pre>
<p>	PHP通过这种比较ugly但是简单高效的方法, 实现了对属性访问权限的标识.知道了这个, 我们就可以干一些不合常理的事请, 比如访问对象的私有/保护属性(见: <a href="http://bugs.php.net/bug.php?id=44273"  target="_blank" >Bug #44273	access to private and protected class variables allowed when casting to array</a>):</p>
<pre name="code"  class="sh_php"  linenum="off"   style="background: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:Monacobackground: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:MonacoConsolasConsolasCourierCouriermonospace;monospace;">
class Foo {
    private $_name = &quot;laruence&quot;;
    protected $_age = 28;
}
$foo = new Foo();
$arr = (array) $foo;
var_dump($arr[&quot;\0Foo\0_name&quot;]);
var_dump($arr[&quot;\0*\0_age&quot;]);
//output:
string(8) &quot;laruence&quot;
int(28)
</pre>
<p>    既然我说到了普通属性, 那么也就有不普通的属性:Static/Constant, 因为静态属性和常量属性都是和类相关而不是和对象相关的, 那么想到然的, 这些属性也就应该保存在类的结构中, 也就是zend_class_entry中. 对象的方法同理也是和类绑定的.</p>
<p>	在zend_class_entry, 有如下HashTable几个成员,</p>
<pre name="code"  class="sh_bash"  linenum="off"   style="background: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:Monacobackground: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:MonacoConsolasConsolasCourierCouriermonospace;monospace;">
1. function_table, 方法集
2. default_static_members, 静态属性
3. default_properties, 默认的属性
4. constants_table, 常量表
</pre>
<p>	属性如其名, 对象类型的属性, 存放在对象的成员中.</p>
<p>   <b>对象的方法</b></p>
<p>	在zend_class_entry中的function_table是个hashTable, 这个函数表的结构和普通的函数表一样(<a href="http://www.laruence.com/2008/08/12/164.html"  target="_blank" >深入理解PHP之函数</a>), 也是以zend_op_array为最终载体, 所以和普通函数一样, 方法也是不区分大小写的, 也是可以附加arg_info的. 而不同的则是, 函数的访问权限则由zend_op_array的fn_flag属性表明.</p>
<p>	我们知道, 在PHP内的函数, 都有统一的参数列表(遵守PHP函数约定开发的前提下),</p>
<pre name="code"  class="sh_c"  linenum="off"   style="background: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:Monacobackground: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:MonacoConsolasConsolasCourierCouriermonospace;monospace;">
#define INTERNAL_FUNCTION_PARAM_PASSTHRU ht, return_value, return_value_ptr, this_ptr, return_value_used TSRMLS_CC
</pre>
<p>   在调用方法的时候, this关键字由函数参数中的this_ptr指明,  而对于用户定义的函数, this关键字则有Zend VM保证.</p>
<p>   说到这里, 举个列子:</p>
<p>   如下代码, 会得到Fatal</p>
<pre name="code"  class="sh_php"  linenum="off"   style="background: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:Monacobackground: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:MonacoConsolasConsolasCourierCouriermonospace;monospace;">
&lt;?php
class Foo {
   public function Say() {
      $this = NULL;
   }
}
?&gt;
//output:
PHP Fatal error:  Cannot re-assign $this in **
</pre>
<p>   这是一个初级的保护措施, 防止this关键字被改写, 难道PHP就仅仅是做了这个保护?  不然,  让我们绕过这个保护措施看看, 如下:</p>
<pre name="code"  class="sh_php"  linenum="off"   style="background: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:Monacobackground: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:MonacoConsolasConsolasCourierCouriermonospace;monospace;">
&lt;?php
class Foo {
    public $id  = &quot;laruence&quot;;
    function Say($arr) {
        extract($arr, EXTR_OVERWRITE);
        var_dump($this);
        var_dump($this-&gt;id);
    }
}
$a = new Foo(); 

$a-&gt;sAY(array(&quot;this&quot; =&gt; NULL)); //只是未来说明方法名不区分大小写.
?&gt;
//output:
NULL
string(8) &quot;laruence&quot;
</pre>
<p>	可见this关键字, 并不是简单的符号表中的item. 是在语法分析阶段, 就由ZEND Engine保证其正确性的, 并Attach在函数的结构体中.</p>
<p>   <b>对象的标准操作</b><br/>
    我们对对象的操作, 比如获取属性, 设置属性, 获取对象的类, 等等, 这些常用的方法, 都是实现在对象的标准方法中的,PHP5中, 提供了23个标准方法.</p>
<p>	在zend_object_value中的handlers指针, 就指向类常用操作的方法集合, 默认的, 这个指针指向:</p>
<pre name="code"  class="sh_c"  linenum="off"   style="background: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:Monacobackground: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:MonacoConsolasConsolasCourierCouriermonospace;monospace;">
ZEND_API zend_object_handlers std_object_handlers = {
    zend_objects_store_add_ref,             /* add_ref */
    zend_objects_store_del_ref,             /* del_ref */
    zend_objects_clone_obj,                 /* clone_obj */

    zend_std_read_property,                 /* read_property */
    zend_std_write_property,                /* write_property */
    zend_std_read_dimension,                /* read_dimension */
    zend_std_write_dimension,               /* write_dimension */
    zend_std_get_property_ptr_ptr,          /* get_property_ptr_ptr */
    NULL,                                   /* get */
    NULL,                                   /* set */
    zend_std_has_property,                  /* has_property */
    zend_std_unset_property,                /* unset_property */
    zend_std_has_dimension,                 /* has_dimension */
    zend_std_unset_dimension,               /* unset_dimension */
    zend_std_get_properties,                /* get_properties */
    zend_std_get_method,                    /* get_method */
    NULL,                                   /* call_method */
    zend_std_get_constructor,               /* get_constructor */
    zend_std_object_get_class,              /* get_class_entry */
    zend_std_object_get_class_name,         /* get_class_name */
    zend_std_compare_objects,               /* compare_objects */
    zend_std_cast_object_tostring,          /* cast_object */
    NULL,                                   /* count_elements */
};
</pre>
<p>	默认的, 也是绝大多数的时候, 都是如上的这些标准方法.</p>
<p>	需要指明的是, _dimension后缀的方法, 指的是通过数组($obj['name'])方式访问对象的属性.</p>
<p><b>魔术方法</b></p>
<p>	魔术方法定义在class_entry中, </p>
<pre name="code"  class="sh_php"  linenum="off"   style="background: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:Monacobackground: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:MonacoConsolasConsolasCourierCouriermonospace;monospace;">
union _zend_function *constructor;
union _zend_function *destructor;
union _zend_function *clone;
union _zend_function *__get;
union _zend_function *__set;
union _zend_function *__unset;
union _zend_function *__isset;
union _zend_function *__call;
union _zend_function *__tostring;
union _zend_function *serialize_func;
union _zend_function *unserialize_func;
</pre>
<p>	魔术方法没有默认值, 在类定义的时刻指定.</p>
<p>	对于一些魔术方法, 比如__get/__set是被标准操作发起调用的, 所以如果我们自己编写扩展中定义的类, 如果不使用标准方法, 那么也需要在适当的时机, 主动调用这些魔术方法.
</p>
<p><script type="text/javascript"  src="http://www.laruence.com/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_bash.js" ></script><script type="text/javascript"  src="http://www.laruence.com/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_c.js" ></script><script type="text/javascript"  src="http://www.laruence.com/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_bash.js" ></script><script type="text/javascript"  src="http://www.laruence.com/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_bash.js" ></script><script type="text/javascript"  src="http://www.laruence.com/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_php.js" ></script><script type="text/javascript"  src="http://www.laruence.com/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_bash.js" ></script><script type="text/javascript"  src="http://www.laruence.com/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_c.js" ></script><script type="text/javascript"  src="http://www.laruence.com/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_php.js" ></script><script type="text/javascript"  src="http://www.laruence.com/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_php.js" ></script><script type="text/javascript"  src="http://www.laruence.com/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_c.js" ></script><script type="text/javascript"  src="http://www.laruence.com/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_php.js" ></script></p>
<hr/><h2>Comments</h2><ul  style="padding-left:1em;font-size:85%;padding-left:1em;font-size:85%;"><li><a href="http://www.laruence.com/2010/05/18/1482.html#comment-2582" >2010/05/18</a>, <a href="http://topsy.com/trackback?utm_source=pingback&amp;utm_campaign=L1&amp;url=http://www.laruence.com/2010/05/18/1482.html"  rel="external nofollow"  class="url" >Tweets that mention 深入理解PHP原理之对象(一) | 风雪之隅 -- Topsy.com</a> writes: [...] This post was mentioned on Twitter by 姚东旭. 姚东旭 said: [推荐] 深入理解PHP原理之对象(一) http://goo.gl/gUMh [...]</li><li><a href="http://www.laruence.com/2010/05/18/1482.html#comment-2591" >2010/05/20</a>, <a href="http://www.phppan.com"  rel="external nofollow"  class="url" >phppan</a> writes: 之前由于一个纠结的私有变量的问题而看过php中类实现的一些代码，但也是粗略了解，
今天拜读鸟哥的文章，再次学习了！</li><li><a href="http://www.laruence.com/2010/05/18/1482.html#comment-2622" >2010/05/21</a>, <a href="http://www.xingai114.com"  rel="external nofollow"  class="url" >xingai</a> writes: <a href="http://www.xingai114.com"  rel="nofollow" >xingai</a>再次学习了！</li><li><a href="http://www.laruence.com/2010/05/18/1482.html#comment-2661" >2010/05/26</a>, <a href="http://crazyphper.com/wblog/archives/777"  rel="external nofollow"  class="url" >深入理解 PHP之require/include顺序 &laquo; 大熊猫 &#8211; konakona ——PHP程序员</a> writes: [...] 本文地址: http://www.laruence.com/2010/05/18/1482.html [...]</li><li><a href="http://www.laruence.com/2010/05/18/1482.html#comment-2760" >2010/06/18</a>, abcasus writes: 辛苦。</li></ul><hr/><small  style="font-size:85%;font-size:85%;">Copyright &copy; 2010 <a href="http://www.laruence.com"  target="_blank" >风雪之隅</a> 版权所有, 转载务必注明. 该Feed只供个人使用, 禁止未注明的转载或商业应用. 非法应用的, 一切法律后果自负. 如有问题, 可发E-mail至my at laruence.com.(Digital Fingerprint: 73540ba0a1738d7d07d4b6038d5615e2)</small>]]></content:encoded>
			<wfw:commentRss>http://www.laruence.com/2010/05/18/1482.html/feed</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>使用PHP_UML生成代码的UML图</title>
		<link>http://www.laruence.com/2010/05/14/1473.html</link>
		<comments>http://www.laruence.com/2010/05/14/1473.html#comments</comments>
		<pubDate>Fri, 14 May 2010 07:38:01 +0000</pubDate>
		<dc:creator>雪候鸟</dc:creator>
				<category><![CDATA[PHP应用]]></category>
		<category><![CDATA[随笔]]></category>
		<category><![CDATA[mapforce]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[php_uml]]></category>
		<category><![CDATA[xmi]]></category>

		<guid isPermaLink="false">http://www.laruence.com/?p=1473</guid>
		<description><![CDATA[在读别人代码的时候, 在没有详细文档的时候, 如何快速的看清整个代码的结构(类结构), 就成为了一个现实的问题.

    今天我就介绍一种, 自动生成UML图的方法.]]></description>
			<content:encoded><![CDATA[<div class="copyright" >
<ul  style="padding-left:1em;font-size:85%;padding-left:1em;font-size:85%;">
<li>作者: laruence(<a href="http://www.laruence.com"  title="风雪之隅"  target="_blank" >http://www.laruence.com</a>)</li>
<li>本文地址: <a href="http://www.laruence.com/2010/05/14/1473.html"  title="Permanet Link to 使用PHP_UML生成代码的UML图" >http://www.laruence.com/2010/05/14/1473.html</a></li>
<li>转载请注明出处 </li>
</ul></div>
<p>
    在读别人代码的时候, 在没有详细文档的时候, 如何快速的看清整个代码的结构(类结构), 就成为了一个现实的问题.</p>
<p>    今天我就介绍一种, 自动生成UML图的方法.</p>
<p>    假设, 我有一个项目文件夹:laruence, 在这个文件夹上有一个文件Root.php(事实上, 无论多级目录, 多个文件, 都可以).</p>
<pre name="code"  class="sh_php"  linenum="off"   style="background: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:Monacobackground: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:MonacoConsolasConsolasCourierCouriermonospace;monospace;">
&lt;?php

abstract class Root {
    private $instance;
    abstract public function Hi();
}

interface Intro {
    public function Say();
}

class Sub extends Root implements Intro {
    private $instance;
    public function Say() {
        echo &quot;I am Laruence&quot;;
    }
    public function Hi() {
        echo &quot;Hello!&quot;;
    }
}
?&gt;
</pre>
<p>    首先, 我们要使用PHP_UML(<a href="http://pear.php.net/package/PHP_UML"  target="_blank" >PHP_UML</a>)根据代码生成XMI.</p>
<p>    使用方法比较简单, 在安装PHP_UML以后, 运行:</p>
<pre name="code"  class="sh_bash"  linenum="off"   style="background: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:Monacobackground: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:MonacoConsolasConsolasCourierCouriermonospace;monospace;">
 phpuml laruence/ -o laruence.xmi -n laruence -f xmi  --pure-object --no-deployment-view  --no-component-view --no-docblocks
</pre>
<p>   会得到一个laruence.xmi文件, phpuml的具体参数可以通过phpuml &#8211;help了解.</p>
<p>   有了xmi以后, 如何转成UML图呢?</p>
<p>   Visio2007不支持导入XMI, 我找到了另外的一个工具:<a href="http://www.altova.com/umodel.html"  target="_blank" >Altova Umodel</a>, 这个工具可以支持XMI到UML图的转换, 需要注册, 不过提供了30天的使用许可(大家要是有更好的替换方案, 欢迎补充).</p>
<p>   在Umodel导入laruence.xmi以后 ,生成UML图, 就得到了如下的PNG:</p>
<div id="attachment_1476"  class="wp-caption aligncenter"  style="width: 570px" ><a href="http://www.laruence.com/wp-content/uploads/laruence1.png" ><img src="http://www.laruence.com/wp-content/uploads/laruence1.png"  alt="UML图"  title="laruence"  width="560"  height="445"  class="size-full wp-image-1476" /></a><p class="wp-caption-text" >UML图</p></div>
<p>   是不是很方便呢?</p>
<p>   另外PHP_UML还可以生成html格式, 做为一种doc gen工具也不错. 更可以通过xmi生成PHP文件.<br/>
<script type="text/javascript"  src="http://www.laruence.com/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_php.js" ></script><script type="text/javascript"  src="http://www.laruence.com/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_bash.js" ></script></p>
<hr/><h2>Comments</h2><ul  style="padding-left:1em;font-size:85%;padding-left:1em;font-size:85%;"><li><a href="http://www.laruence.com/2010/05/14/1473.html#comment-2568" >2010/05/14</a>, <a href="http://54chen.com"  rel="external nofollow"  class="url" >cc0cc</a> writes: 哥学社不遗余力地顶起，有没有反向的办法，通过uml生成php代码？</li><li><a href="http://www.laruence.com/2010/05/14/1473.html#comment-2569" >2010/05/14</a>, toms writes: 要是能进一步识别程序的调用关系就更好啦</li><li><a href="http://www.laruence.com/2010/05/14/1473.html#comment-2570" >2010/05/14</a>, <a href="http://www.laruence.com"  rel="external nofollow"  class="url" >雪候鸟</a> writes: @cc0cc 有, visio 03据说有个插件, 可以把UML图导出成XMI. PHP_UML就可以根据XMI生成PHP代码了, 当然, mapForce也可以导出XMI</li><li><a href="http://www.laruence.com/2010/05/14/1473.html#comment-2571" >2010/05/14</a>, <a href="http://topsy.com/trackback?utm_source=pingback&amp;utm_campaign=L1&amp;url=http://www.laruence.com/2010/05/14/1473.html"  rel="external nofollow"  class="url" >Tweets that mention 使用PHP_UML生成代码的UML图 | 风雪之隅 -- Topsy.com</a> writes: [...] This post was mentioned on Twitter by 小白. 小白 said: 使用PHP_UML生成代码的UML图 - http://goo.gl/UAQp [...]</li><li><a href="http://www.laruence.com/2010/05/14/1473.html#comment-2580" >2010/05/18</a>, 玉丰 writes: 哈哈，去试试。还有，建议换个验证码，现在这个太难用了。</li><li><a href="http://www.laruence.com/2010/05/14/1473.html#comment-2641" >2010/05/23</a>, <a href="http://www.jaceju.net/blog/?p=1175"  rel="external nofollow"  class="url" >網站製作學習誌 &raquo; [Web] 連結分享</a> writes: [...] 使用PHP_UML生成代码的UML图 [...]</li><li><a href="http://www.laruence.com/2010/05/14/1473.html#comment-2704" >2010/06/05</a>, luckgo writes: 我折腾到深夜，装了Altova MapForce,但怎么也找不到导入xmi的菜单，倒是在google上找到Altova Umodel导入xmi的介绍，请问Laruence，是不是你搞错了耶？</li><li><a href="http://www.laruence.com/2010/05/14/1473.html#comment-2705" >2010/06/05</a>, <a href="http://www.laruence.com"  rel="external nofollow"  class="url" >雪候鸟</a> writes: @luckgo  正是, 正是, 多谢指正, 已经修改.</li><li><a href="http://www.laruence.com/2010/05/14/1473.html#comment-2943" >2010/07/16</a>, <a href="http://dothing"  rel="external nofollow"  class="url" >lake</a> writes: 好东西，谢谢，今晚有得折腾了。哈哈</li><li><a href="http://www.laruence.com/2010/05/14/1473.html#comment-3080" >2010/08/11</a>, tirisfal writes: 如果是导出html，怎么支持utf-8呢？</li></ul><hr/><small  style="font-size:85%;font-size:85%;">Copyright &copy; 2010 <a href="http://www.laruence.com"  target="_blank" >风雪之隅</a> 版权所有, 转载务必注明. 该Feed只供个人使用, 禁止未注明的转载或商业应用. 非法应用的, 一切法律后果自负. 如有问题, 可发E-mail至my at laruence.com.(Digital Fingerprint: 73540ba0a1738d7d07d4b6038d5615e2)</small>]]></content:encoded>
			<wfw:commentRss>http://www.laruence.com/2010/05/14/1473.html/feed</wfw:commentRss>
		<slash:comments>10</slash:comments>
		</item>
		<item>
		<title>Javascript原型链和原型的一个误区</title>
		<link>http://www.laruence.com/2010/05/13/1462.html</link>
		<comments>http://www.laruence.com/2010/05/13/1462.html#comments</comments>
		<pubDate>Thu, 13 May 2010 15:52:09 +0000</pubDate>
		<dc:creator>雪候鸟</dc:creator>
				<category><![CDATA[Js/CSS]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[prototype]]></category>
		<category><![CDATA[__proto__]]></category>

		<guid isPermaLink="false">http://www.laruence.com/?p=1462</guid>
		<description><![CDATA[之前我对Javascript的原型链中, 原型继承与标识符查找有些迷惑, 

    如, 如下的代码:
<coolcode lang="javascript" linenum="off">
function Foo() {};
var foo = new Foo();
Foo.prototype.label = "laruence";
alert(foo.label); //output: laruence
alert(Foo.label);//output: undefined
</coolcode>]]></description>
			<content:encoded><![CDATA[<div class="copyright" >
<ul  style="padding-left:1em;font-size:85%;padding-left:1em;font-size:85%;">
<li>作者: laruence(<a href="http://www.laruence.com"  title="风雪之隅"  target="_blank" >http://www.laruence.com</a>)</li>
<li>本文地址: <a href="http://www.laruence.com/2010/05/13/1462.html"  title="Permanet Link to Javascript原型链和原型的一个误区" >http://www.laruence.com/2010/05/13/1462.html</a></li>
<li>转载请注明出处 </li>
</ul></div>
<p>
    之前我对Javascript的原型链中, 原型继承与标识符查找有些迷惑, </p>
<p>    如, 如下的代码:</p>
<pre name="code"  class="sh_javascript"  linenum="off"   style="background: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:Monacobackground: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:MonacoConsolasConsolasCourierCouriermonospace;monospace;">
function Foo() {};
var foo = new Foo();
Foo.prototype.label = &quot;laruence&quot;;
alert(foo.label); //output: laruence
alert(Foo.label);//output: undefined
</pre>
<p>    今天看到了如下这个图:<br/>
<div id="attachment_1463"  class="wp-caption aligncenter"  style="width: 621px" ><a href="http://www.laruence.com/wp-content/uploads/javascript_object_layout.jpg" ><img src="http://www.laruence.com/wp-content/uploads/javascript_object_layout.jpg"  alt="Javascript object layout"  title="javascript_object_layout"  width="611"  height="760"  class="size-full wp-image-1463" /></a><p class="wp-caption-text" >Javascript object layout</p></div></p>
<p>    另外, 在<a href="http://www.mollypages.org/misc/js.mp"  target="_blank" >Javascript Object Hierarchy</a>看到: </p>
<blockquote><p>
   The prototype is only used for properties inherited by objects/instances created by that function. The function itself does not use the associated prototype.
</p></blockquote>
<p>    也就是说, 函数对象的prototype并不作用于原型链查找过程中, </p>
<p>    今天在firefox下发现(因为firefox通过__proto__暴露了[[prototype]]), 真正参与标识符查找的是函数对象的__proto__, </p>
<pre name="code"  class="sh_javascript"  linenum="off"   style="background: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:Monacobackground: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:MonacoConsolasConsolasCourierCouriermonospace;monospace;">
function Foo() {};
var foo = new Foo();
Foo.__proto__.label = &quot;laruence&quot;;
alert(Foo.label); //output: laruence
alert(foo.label);//output: undefined
</pre>
<p>     而, 显然的:</p>
<pre name="code"  class="sh_javascript"  linenum="off"   style="background: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:Monacobackground: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:MonacoConsolasConsolasCourierCouriermonospace;monospace;">
function Foo() {};
alert(Foo.__proto__ === Foo.prototype); //output: false
</pre>
<p>     另外, 也解释了, </p>
<pre name="code"  class="sh_javascript"  linenum="off"   style="background: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:Monacobackground: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:MonacoConsolasConsolasCourierCouriermonospace;monospace;">
alert(Object.forEach); // undefined

Function.prototype.forEach = function(object, block, context) {
    for (var key in object) {
        if (typeof this.prototype[key] == &quot;undefined&quot;) {
            block.call(context, object[key], key, object);
        }
    }

};

alert(Object.forEach);
alert(Function.forEach);
alert(Object.forEach === Function.forEach); // true
</pre>
<p><script type="text/javascript"  src="http://www.laruence.com/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_javascript.js" ></script><script type="text/javascript"  src="http://www.laruence.com/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_javascript.js" ></script><script type="text/javascript"  src="http://www.laruence.com/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_javascript.js" ></script><script type="text/javascript"  src="http://www.laruence.com/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_javascript.js" ></script></p>
<hr/><h2>Comments</h2><ul  style="padding-left:1em;font-size:85%;padding-left:1em;font-size:85%;"><li><a href="http://www.laruence.com/2010/05/13/1462.html#comment-2565" >2010/05/14</a>, <a href="http://www.jaceju.net/blog/?p=1139"  rel="external nofollow"  class="url" >網站製作學習誌 &raquo; [Web] 連結分享</a> writes: [...] Javascript原型链和原型的一个误区 [...]</li><li><a href="http://www.laruence.com/2010/05/13/1462.html#comment-2610" >2010/05/21</a>, 牛 writes: 牛牛牛牛牛</li><li><a href="http://www.laruence.com/2010/05/13/1462.html#comment-2868" >2010/07/02</a>, J writes: 你好，想请教一个问题。


	var A = (window.getSelection)?window.getSelection():document.selection;
	if(!A) {
		return NULL;
	}
	var B = (A.rangeCount&gt;0)?A.getRangeAt(0):A.createRange()
	//alert(A.rangeCount&gt;0);
	obj.currPos = B.duplicate();
	if (obj.currPos) {
		//alert(obj.currPos.htmlText);
		//obj.currPos.text = str
		obj.currPos.htmlText = str //!!!!!!!!!!!!!

	}
	else {obj.innerHTML+=str}//直接把参数str的值添加到对象obj的值后面 


为什么在obj.currPos.htmlText会报doesn't support this action这个错呢？alert()的时候却没有报错。</li><li><a href="http://www.laruence.com/2010/05/13/1462.html#comment-2944" >2010/07/16</a>, <a href="http://dothing"  rel="external nofollow"  class="url" >lake</a> writes: 这图有点乱，我推荐这幅图
http://images.cnblogs.com/cnblogs_com/riccc/js/js_object_model.jpg
出自文章
http://www.cnblogs.com/RicCC/archive/2008/02/15/JavaScript-Object-Model-Execution-Model.html

当年看到这幅图，豁然开朗，希望对你有帮助</li></ul><hr/><small  style="font-size:85%;font-size:85%;">Copyright &copy; 2010 <a href="http://www.laruence.com"  target="_blank" >风雪之隅</a> 版权所有, 转载务必注明. 该Feed只供个人使用, 禁止未注明的转载或商业应用. 非法应用的, 一切法律后果自负. 如有问题, 可发E-mail至my at laruence.com.(Digital Fingerprint: 73540ba0a1738d7d07d4b6038d5615e2)</small>]]></content:encoded>
			<wfw:commentRss>http://www.laruence.com/2010/05/13/1462.html/feed</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>深入理解PHP之require/include顺序</title>
		<link>http://www.laruence.com/2010/05/04/1450.html</link>
		<comments>http://www.laruence.com/2010/05/04/1450.html#comments</comments>
		<pubDate>Tue, 04 May 2010 10:03:53 +0000</pubDate>
		<dc:creator>雪候鸟</dc:creator>
				<category><![CDATA[PHP应用]]></category>
		<category><![CDATA[PHP源码分析]]></category>
		<category><![CDATA[include]]></category>
		<category><![CDATA[require]]></category>
		<category><![CDATA[顺序]]></category>

		<guid isPermaLink="false">http://www.laruence.com/2010/05/04/1450.html</guid>
		<description><![CDATA[在大型的Web项目中, include_path是一个模块化设计的根本中的根本(当然,现在也有很多基于autoload的设计, 这个不影响本文的探讨), 但是正是因为include_path, 经常会让我们遇到一些因为没有找到正确的文件而导致的看似"诡异"的问题.

也就有了如下的疑问:

include_path是怎么起作用的?

如果有多个include_path顺序是怎么样的? 

什么情况下include_path不起作用?]]></description>
			<content:encoded><![CDATA[<div class="copyright" >
<ul  style="padding-left:1em;font-size:85%;padding-left:1em;font-size:85%;">
<li>作者: laruence(<a href="http://www.laruence.com"  title="风雪之隅"  target="_blank" >http://www.laruence.com</a>)</li>
<li>本文地址: <a href="http://www.laruence.com/2010/05/04/1450.html"  title="Permanet Link to 深入理解PHP之require/include顺序" >http://www.laruence.com/2010/05/04/1450.html</a></li>
<li>转载请注明出处 </li>
</ul></div>
<p>
在大型的Web项目中, include_path是一个模块化设计的根本中的根本(当然,现在也有很多基于autoload的设计, 这个不影响本文的探讨), 但是正是因为include_path, 经常会让我们遇到一些因为没有找到正确的文件而导致的看似&#8221;诡异&#8221;的问题.</p>
<p>也就有了如下的疑问:</p>
<p>include_path是怎么起作用的?</p>
<p>如果有多个include_path顺序是怎么样的? </p>
<p>什么情况下include_path不起作用?</p>
<p>今天, 我就全面的介绍下这个问题, 先从一个例子开始吧.</p>
<p>如下的目录结构:</p>
<pre name="code"  class="sh_php"  linenum="off"   style="background: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:Monacobackground: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:MonacoConsolasConsolasCourierCouriermonospace;monospace;">
  root
    ├ 1.php
    ├ 3.php
    └ subdir
    	├ 2.php
		└ 3.php
</pre>
<p>在1.php中:</p>
<pre name="code"  class="sh_php"  linenum="off"   style="background: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:Monacobackground: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:MonacoConsolasConsolasCourierCouriermonospace;monospace;">
&lt;?php
ini_set(&quot;include_path&quot;, &quot;.:path_to_subdir&quot;);
require(&quot;2.php&quot;);
?&gt;
</pre>
<p>而在2.php中:</p>
<pre name="code"  class="sh_php"  linenum="off"   style="background: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:Monacobackground: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:MonacoConsolasConsolasCourierCouriermonospace;monospace;">
&lt;?php
require(&quot;3.php&quot;);
?&gt;
</pre>
<p>而在root目录下的3.php打印出&#8221;root&#8221;, 在subdir目录下的3.php打印出&#8221;subdir&#8221;;</p>
<p>现在, 我的问题来了:</p>
<p>1. 当在root目录下运行1.php, 会得到什么输出?</p>
<p>2. 在subdir下运行上一级目录的1.php, 有会得到什么输出?</p>
<p>3. 当取消include_path中的当前目录path(也就是include_path=&#8221;path_to_subdir&#8221;), 上面俩个问题又会是什么输出?</p>
<p><b>PHP中的include_path</b></p>
<p>PHP在遇到require(_once)/include(_once)的指令的时候, 首先会做如下的判断:</p>
<pre name="code"  class="sh_bash"  linenum="off"   style="background: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:Monacobackground: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:MonacoConsolasConsolasCourierCouriermonospace;monospace;">
要包含的文件路径是绝对路径么?
 如果是, 则直接包含, 并结束.
 如果不是, 进入另外的逻辑(经过多次调用, 宏展开后进入_php_stream_fopen_with_path)寻找此文件.
</pre>
<p>接下来, 在_php_stream_fopen_with_path中, 会做如下判断:</p>
<pre name="code"  class="sh_bash"  linenum="off"   style="background: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:Monacobackground: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:MonacoConsolasConsolasCourierCouriermonospace;monospace;">
要包含的文件路径是相对路径么(形如./file, ../dir/file, 以下用&quot;目录相对路径代替&quot;)?
 如果是, 则跳过include_path的作用逻辑, 直接解析相对路径(随后单独介绍).
</pre>
<p> 会根据include_path,和当前执行文件的path组成一个待选的目录列表, 比如对于文章前面的例子来说, 会形成一个如下的待选列表</p>
<pre name="code"  class="sh_bash"  linenum="off"   style="background: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:Monacobackground: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:MonacoConsolasConsolasCourierCouriermonospace;monospace;">
&quot;.:path_to_subdir:current_script_dir&quot;
</pre>
<p>然后, 依次从待选列表头部开始, 根据DEFAULT_DIR_SEPARATOR(本文的环境是&#8221;:&#8221;)取出待选列表中的一个路径, 然后把要包含的文件名附加在这个路径后面, 进行尝试. 如果成功包含, 则返回, 否则继续下一个待选路径.</p>
<p>到现在为止, 我们已经可以回答我开头提出的3个问题了.</p>
<p>1. 因为在root目录下执行, 所以在1.php中包含2.php的时候, include_path的第二个待选路径起了作用(path_to_subdir), 找到了path_to_subdir/2.php, 而在2.php包含3.php的时候, 当前工作目录是root下, 所以在包含3.php的时候, include_path的第一个待选路径&#8221;.&#8221;(当前工作目录)下就找到的匹配的文件, 所以得到的输出是&#8221;root&#8221;.</p>
<p>2. 同1, 只不过当前的路径是subdir, 所以得到的输出是&#8221;subdir&#8221;.</p>
<p>3. 因为没有了当前路径为include_path, 所以在root目录下运行的时候2.php中包含3.php的时候, 是path_to_subdir起了作用, 所以无论在root还是subdir都将得到&#8221;subdir&#8221;的输出.<br/>
   而如果在2.php中清空include_path,</p>
<pre name="code"  class="sh_php"  linenum="off"   style="background: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:Monacobackground: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:MonacoConsolasConsolasCourierCouriermonospace;monospace;">
&lt;?php
ini_set(&quot;include_path&quot;, '');
require(&quot;3.php&quot;);
?&gt;
</pre>
<p>   那么将会是current_script_dir起作用, 而这个时候current_script_dir是2.php的路径, 所以还是会得到&#8221;subdir&#8221;的输出.</p>
<p><b>目录相对路径</b></p>
<p>在使用目录相对路径的情况下, 相对路径的基点, 永远都是当前工作目录.</p>
<p>为了说明在目录相对路径下的情况,我们再看个列子, 还是上面的目录结构, 只不过1.php变成了:</p>
<pre name="code"  class="sh_php"  linenum="off"   style="background: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:Monacobackground: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:MonacoConsolasConsolasCourierCouriermonospace;monospace;">
&lt;?php
ini_set(&quot;include_path&quot;, &quot;/&quot;);
require(&quot;./subdir/2.php&quot;);
?&gt;
</pre>
<p>2.php变成了:</p>
<pre name="code"  class="sh_php"  linenum="off"   style="background: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:Monacobackground: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:MonacoConsolasConsolasCourierCouriermonospace;monospace;">
&lt;?php
require(&quot;./3.php&quot;);
?&gt;
</pre>
<p>如果在root目录下执行, 2.php中寻找3.php将会在当前目录的相对路径下寻找, 所以得到的输出是&#8221;root&#8221;, 而如果是在subdir下执行上一级目录的1.php(php -f ../1.php), 将会因为在subdir下找不到&#8221;./subdir/2.php&#8221;而异常退出.</p>
<p><b>后记</b></p>
<p> 1. 因为使用include_path和相对路径的情况下, 性能会和寻找的次数有关, 最坏的情况下, 如果你有10个include_path, 那么最多可能会重试11次才能找到要包含的文件,  所以, 在能使用绝对路径的情况下最好使用绝对路径.</p>
<p> 2. 因为目录相对路径的basedir, 永远都是当前工作路径, 如果要使用, 需要和实际部署路径相关,  所以实际使用的很少(当然, 也有借助chdir来完成的模块).</p>
<p> 3. 在模块化的系统设计中,  一般应该在模块内, 通过获取模块的部署路径(dirname(__FILE__), php5.3以后更是提供了__DIR__常量)从而使用绝对路径.</p>
<p><script type="text/javascript"  src="http://www.laruence.com/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_php.js" ></script><script type="text/javascript"  src="http://www.laruence.com/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_php.js" ></script><script type="text/javascript"  src="http://www.laruence.com/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_php.js" ></script><script type="text/javascript"  src="http://www.laruence.com/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_bash.js" ></script><script type="text/javascript"  src="http://www.laruence.com/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_bash.js" ></script><script type="text/javascript"  src="http://www.laruence.com/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_bash.js" ></script><script type="text/javascript"  src="http://www.laruence.com/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_php.js" ></script><script type="text/javascript"  src="http://www.laruence.com/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_php.js" ></script><script type="text/javascript"  src="http://www.laruence.com/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_php.js" ></script></p>
<hr/><h2>Comments</h2><ul  style="padding-left:1em;font-size:85%;padding-left:1em;font-size:85%;"><li><a href="http://www.laruence.com/2010/05/04/1450.html#comment-2545" >2010/05/04</a>, <a href="http://blog.webfuns.net"  rel="external nofollow"  class="url" >tomheng</a> writes: 一直在读Laruence老师的博文，很受益。</li><li><a href="http://www.laruence.com/2010/05/04/1450.html#comment-2546" >2010/05/05</a>, CFC4N writes: 感谢鸟老师，一直学习中。。</li><li><a href="http://www.laruence.com/2010/05/04/1450.html#comment-2547" >2010/05/05</a>, N writes: &gt;&gt;3. 因为没有了当前路径为include_path, 所以在2.php中包含3.php的时候, 是current_script_dir起了作用, 而current_script_dir是2.php的路径, 所以无论在root还是subdir都将得到”subdir”的输出.

2.php包含3.php时不应该是path_to_subdir起作用么？</li><li><a href="http://www.laruence.com/2010/05/04/1450.html#comment-2548" >2010/05/05</a>, <a href="http://hi.baidu.com/dinghwy"  rel="external nofollow"  class="url" >dd</a> writes: 主要是在include嵌套的时候，都是以最开始执行的php文件所在的路径为cwd，这样就都理解了。</li><li><a href="http://www.laruence.com/2010/05/04/1450.html#comment-2549" >2010/05/05</a>, <a href="http://www.laruence.com"  rel="external nofollow"  class="url" >雪候鸟</a> writes: @N 哦,对, 我设计的例子有问题, 其实是为了说明current_script_dir, 谢谢指正.</li><li><a href="http://www.laruence.com/2010/05/04/1450.html#comment-2552" >2010/05/05</a>, <a href="http://www.54chen.com/cc/php-require-include.html"  rel="external nofollow"  class="url" >从php核心代码看require和include的区别 - 五四陈科学院-php和java第一院</a> writes: [...] 见到鸟哥的一文：深入理解PHP之require/include顺序 http://www.laruence.com/2010/05/04/1450.html [...]</li><li><a href="http://www.laruence.com/2010/05/04/1450.html#comment-2553" >2010/05/05</a>, yufeng writes: 学习……这个问题本质上是个寻找文件优先级的问题吧，
基本上的顺序是：

1.绝对路径
2.遍历include_path中的路径
3.相对于current_script_dir的相对路径

而且，有两点总结：
  1.只要找到了，就不再向下寻找了。
  2.如果找不到，就一定会向下寻找。即使使用绝对路径，当文件不存在时，PHP依然会按这个次序进入include_path和current_script_dir的相对路径中寻找（当然更找不到了）。</li><li><a href="http://www.laruence.com/2010/05/04/1450.html#comment-2554" >2010/05/06</a>, <a href="http://www.uini.net/2010/05/php-depth-understanding-of-the-require-include-the-order-of.html"  rel="external nofollow"  class="url" >深入理解PHP之require/include顺序-传播、沟通、分享-一直“有你”</a> writes: [...] 本文地址: http://www.laruence.com/2010/05/04/1450.html [...]</li><li><a href="http://www.laruence.com/2010/05/04/1450.html#comment-2733" >2010/06/10</a>, <a href="http://www.hi-av.com"  rel="external nofollow"  class="url" >av</a> writes: 一直学习中。。...</li><li><a href="http://www.laruence.com/2010/05/04/1450.html#comment-2874" >2010/07/02</a>, <a href="http://blog.haohtml.com/index.php/archives/4311"  rel="external nofollow"  class="url" >从php核心代码看require和include的区别 | haohtml&#39;s blog</a> writes: [...] 见到鸟哥的一文：深入理解PHP之require/include顺序 http://www.laruence.com/2010/05/04/1450.html [...]</li><li><a href="http://www.laruence.com/2010/05/04/1450.html#comment-2885" >2010/07/05</a>, <a href="http://blog.haohtml.com/index.php/archives/4380"  rel="external nofollow"  class="url" >深入理解 PHP之require/include顺序 | haohtml&#39;s blog</a> writes: [...] 本文地址: http://www.laruence.com/2010/05/04/1450.html [...]</li></ul><hr/><small  style="font-size:85%;font-size:85%;">Copyright &copy; 2010 <a href="http://www.laruence.com"  target="_blank" >风雪之隅</a> 版权所有, 转载务必注明. 该Feed只供个人使用, 禁止未注明的转载或商业应用. 非法应用的, 一切法律后果自负. 如有问题, 可发E-mail至my at laruence.com.(Digital Fingerprint: 73540ba0a1738d7d07d4b6038d5615e2)</small>]]></content:encoded>
			<wfw:commentRss>http://www.laruence.com/2010/05/04/1450.html/feed</wfw:commentRss>
		<slash:comments>11</slash:comments>
		</item>
	</channel>
</rss>
