<?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>潘锦的空间 &#187; PHP</title>
	<atom:link href="https://www.phppan.com/tag/php-extention-source-code/feed/" rel="self" type="application/rss+xml" />
	<link>https://www.phppan.com</link>
	<description>SaaS SaaS架构 团队管理 技术管理 技术架构 PHP 内核 扩展 项目管理</description>
	<lastBuildDate>Sat, 04 Apr 2026 01:19:58 +0000</lastBuildDate>
	<language>zh-CN</language>
		<sy:updatePeriod>hourly</sy:updatePeriod>
		<sy:updateFrequency>1</sy:updateFrequency>
	<generator>https://wordpress.org/?v=3.9.40</generator>
	<item>
		<title>PHP面向对象的历史</title>
		<link>https://www.phppan.com/2013/10/php-oop-history/</link>
		<comments>https://www.phppan.com/2013/10/php-oop-history/#comments</comments>
		<pubDate>Sun, 06 Oct 2013 02:27:09 +0000</pubDate>
		<dc:creator><![CDATA[admin]]></dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[OOP]]></category>
		<category><![CDATA[面向对象]]></category>

		<guid isPermaLink="false">http://www.phppan.com/?p=1861</guid>
		<description><![CDATA[PHP面向对象的历史 PHP最开始的perl脚本，到C语言版的PHP/FI，再到PHP/FI 2.0、PHP3 [&#8230;]]]></description>
				<content:encoded><![CDATA[<h1>PHP面向对象的历史</h1>
<p>PHP最开始的perl脚本，到C语言版的PHP/FI，再到PHP/FI 2.0、PHP3.0，直到PHP4，引入Zend Engine使PHP更加的强大，并在PHP5引入新的Zend Engine2，重写PHP的面向对象模型，使PHP不仅可以快速开发，同时也可以实现更加复杂的架构，甚至满足企业应用。</p>
<p>PHP最开始并没有面向对象，直到PHP4才有一些面向对象的影子，到PHP5才真正实现面向对象模型。大概来说，PHP面向对象历史包括两个阶段：</p>
<h2 >PHP4-Zend Engine阶段  </h2>
<p>此时并没有真正的面向对象，因为PHP根本没有实现面向对象的三大特性，所有的成员方法和成员函数都是公有的，成员变量通过var声明。</p>
<p>此时的构造函数和类名一样，序列和反序列化时能调用魔术函数_sleep 和 __wakeup。嗯，这是是叫魔术函数而不是魔术方法，因为它本来就是独立出来的函数，当执行序列化时，PHP会判断当前变量是什么类型，如果是IS_OBJECT，则会自动调用__sleep函数。
</p>
<p>在4.0.2以后可以使用parent::调用父类的方法。这里的parent仅仅是函数调用时的一个特殊处理。</p>
<p>在PHP的内核实现中类和函数共用一个opcode（ZEND_DECLARE_FUNCTION_OR_CLASS），通过extended_value字段区分，类和函数的存储已经区分开。</p>
<p>总的来说，PHP4的面向对象有点脚手架的味道，各种定制后有了一些面向对象的形。</p>
<h2>PHP5-Zend Engine2阶段</h2>
<p>5.0.0引入Zend Engine2，至此PHP才真正引入了面向对象的机制。<br />
Zend Engine2重写了PHP的面向对象模型，其中包括对构建器和析构器的定义，增加的私有成员变量、静态成员变量、接口、重载等面向对象特性以及新增加了魔术方法实现。除了面向对象特性外，Zend Engine2引入了异常处理控制流。具体见： <a href="http://www.zend.com/engine2/ZendEngine-2.0.pdf" target="_blank">http://www.zend.com/engine2/ZendEngine-2.0.pdf</a></p>
<p>5.1.0 新增：__isset 和 __unset 方法。</p>
<p>5.3.0  新增： __invoke 方法、 后期静态绑定、 heredoc 和 nowdoc 支持类的常量和属性的定义、__callStatic 方法等</p>
<p>5.4.0 增加Traits，Trait 和类相似，但它的目的是用细粒度和一致的方式来组合功能。Trait 不能实例化。它为传统继承增加了水平特性的组合；也就是说，应用类的成员不需要继承。</p>
<p>总的来说，PHP5已经实现了面向对象模型，可以基于PHP5实现企业级应用。但是一些新的功能和特性，在实际的开发过程中使用得并不多，如Traits、命名空间等。很多时候，业务决定技术，需求决定实现。</p>
<p>然，此篇仅为整理之作，只为理自己对于PHP面向对象的思路。<br />
久不沾笔，些许生疏。</p>
<h2>参考资料</h2>
<ul>
<li>http://php.net/manual/zh/history.php.php</li>
<li>http://www.php.net/ChangeLog-4.php
</li>
<li>http://www.php.net/ChangeLog-5.php</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>https://www.phppan.com/2013/10/php-oop-history/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>使用Yii框架中遇到的三个问题</title>
		<link>https://www.phppan.com/2013/05/yii-three-question/</link>
		<comments>https://www.phppan.com/2013/05/yii-three-question/#comments</comments>
		<pubDate>Sun, 26 May 2013 10:25:56 +0000</pubDate>
		<dc:creator><![CDATA[admin]]></dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Yii框架]]></category>

		<guid isPermaLink="false">http://www.phppan.com/?p=1843</guid>
		<description><![CDATA[使用Yii框架中遇到的三个问题 1、main.php文件中欲引入全局变量的问题 还原一下此问题：在Yii框架中 [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>使用Yii框架中遇到的三个问题</p>
<p><strong>1、main.php文件中欲引入全局变量的问题</strong></p>
<p>还原一下此问题：在Yii框架中，main.php一般会作为整个应用的配置文件，保存Application的各种参数，直接return数组。在使用的过程中，因为main.php文件一定会被Yii提前加载，所以将一些全局性的操作也放在了此文件，加载一些类操作啥的没有什么问题，当有一次加了一个全局变量，并且在其它地方使用global获取全局变量时，发现无论我如何努力都得到的是NULL。各种尝试后，终于，把引入的位置放在入口文件index.php，得以解决。什么原因？我们重现一下Yii的main.php文件加载。如下代码</p>
<p>index.php文件：</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="php" style="font-family:monospace;"> <span style="color: #000000; font-weight: bold;">class</span> CApp <span style="color: #009900;">&#123;</span>
        <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> __construct<span style="color: #009900;">&#40;</span><span style="color: #000088;">$config</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
            <span style="color: #000088;">$config</span> <span style="color: #339933;">=</span> <span style="color: #b1b100;">require</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$config</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #000088;">$path</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">&quot;main.php&quot;</span><span style="color: #339933;">;</span>
    <span style="color: #000088;">$app</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> CApp<span style="color: #009900;">&#40;</span><span style="color: #000088;">$path</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #000000; font-weight: bold;">global</span> <span style="color: #000088;">$global</span><span style="color: #339933;">;</span>
    <span style="color: #990000;">var_dump</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$global</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></td></tr></table></div>

<p>main.php文件：</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="php" style="font-family:monospace;"> <span style="color: #000000; font-weight: bold;">&lt;?php</span>
    <span style="color: #000088;">$global</span> <span style="color: #339933;">=</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #cc66cc;">1</span><span style="color: #339933;">,</span> <span style="color: #cc66cc;">2</span><span style="color: #339933;">,</span> <span style="color: #cc66cc;">3</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #b1b100;">return</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></td></tr></table></div>

<p>两个文件放在同一目录，直接运行index.php，输出的$global为NULL，如果我们在CApp的构造函数中直接输出$global，则会有结果输出。什么原因？作用域的问题！</p>
<p>当我们在main.php文件中定义了一个变量，虽然是想将其作为全局变量使用，但是当我们在局部的作用域中require时，其仅仅作为一个局部作用域的变量存在。我们在TIPI中有说到函数调用是嵌套的，每个嵌套都会有一个作用域，在这个作用域中的变量仅在当前有效，嵌套结束，变量生命周期结束。</p>
<p>因此，我们如果想把main.php中的全局变量真的作为整个应用的全局变量使用，则需要在入口文件的作用域中require main.php文件。</p>
<p><strong>2、引入第三方扩展时的class_exists问题</strong></p>
<p>Yii框架Yii基于PHP5的autoload机制来提供类的自动加载功能，自动加载器为YiiBase类的静态方法autoload()。当程序中用new创建对象或访问到类的静态成员，PHP将类名传递给类加载器，由类加载器完成类文件的include。但是如果我们引入了第三方扩展，而第三方扩展的命名规则和Yii的不一样，于是我们会经常看到报错说  require XXX 文件失败。如果你在google中搜索“yii framework class_exists”，你会发现Yii框架的作用Xue  Qiang有回答使用者可以通过使用类似于： class_exists(&#8216;MyClass&#8217;, false)的方式。</p>
<p>class_exists函数检查类是否已定义，如果由 class_name 所指的类已经定义，此函数返回 TRUE，否则返回  FALSE。在PHP内核中，此函数会查找当前类表中由 class_name  所指的类是否存在，在查找之前会全部转化为小写，所以不会区分大小写。其第二个参数是指是否使用autoload，默认为使用，此时class_exists函数会先执行autoload，然后再查找执行了autoload后类表中由  class_name 所指的类是否存在。因此我们可以通过设置第二个参数其为FALSE来绕过自动加载。</p>
<p>这可以解决问题，但是如果我们使用的是无法修改的第三方代码呢？怎么办？我自己是简单的hack了下，在调用第三方的操作之就将需要的类给加载了。</p>
<p>后来又采用了另一种解决方案：直接使用Yii:import的第二个参数，强制加载整个目录。</p>
<p><strong>3、Yii的错误日志</strong></p>
<p>问题就不细述了，只是将生产环境的配置整到了开发环境，于是错误看不到了。调整了下日志的规则，就OK了。</p>
<p>Yii对错误日志的处理依赖于PHP的set_error_handler函数和set_exception_handler函数。在CApplication的initSystemHandlers方法中有对这两个函数的处理。</p>
]]></content:encoded>
			<wfw:commentRss>https://www.phppan.com/2013/05/yii-three-question/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>PHP中的前缀自增(++i) 和后缀自增 (i++)</title>
		<link>https://www.phppan.com/2011/05/pre_inc-and-post_inc-in-php/</link>
		<comments>https://www.phppan.com/2011/05/pre_inc-and-post_inc-in-php/#comments</comments>
		<pubDate>Mon, 16 May 2011 01:28:21 +0000</pubDate>
		<dc:creator><![CDATA[admin]]></dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[PHP应用]]></category>
		<category><![CDATA[自增]]></category>

		<guid isPermaLink="false">http://www.phppan.com/?p=1374</guid>
		<description><![CDATA[当我们学第一门语言时，比如大学课程中的C语言程序设计，也许曾经被前缀自增(++i) 和后缀自增 (i++)纠结 [&#8230;]]]></description>
				<content:encoded><![CDATA[<p style="text-indent: 2em;">当我们学第一门语言时，比如大学课程中的C语言程序设计，也许曾经被前缀自增(++i) 和后缀自增 (i++)纠结过。 曾经以为我们懂了：</p>
<ul>
<li>i++ ：先引用后增加，先在i所在的表达式中使用i的当前值，后让i加1</li>
<li>++i ：先增加后引用，让i先加1，然后在i所在的表达式中使用i的新值</li>
</ul>
<p style="text-indent: 2em;">这个表达基本没错，只能说不够精确。在《Expert C Programming》这本书中的附录中，有这样一段说明： ++i表示取i的地址，增加它的内容，然后把值放在寄存器中；i++表示取i的地址，把它的值装入寄存器中，然后增加内存中的i的值。 这里的寄存器存放的就是我们在表达式中使用的值。</p>
<p style="text-indent: 2em;">在PHP中也有++$i和$i++，那么Zend内核是如何实现这两种自增方式的呢？ 看下面一个例子，在不运行这段代码的情况下，你认为会输出什么呢？</p>
<pre style="background-color: #333333; color: #ffffff; font: normal normal normal 13px/normal 'Bitstream Vera Sans Mono', 'DejaVu Sans Mono', 'Courier New', monospace; overflow-x: auto; overflow-y: auto; padding: 10px;"><span style="color: #6d9cbe;">$i</span> <span style="color: #e0882f;">=</span> <span style="color: #1299da;">0</span><span style="color: #e0882f;">;</span>
<span style="color: #6d9cbe;">$i</span> <span style="color: #e0882f;">=</span> <span style="color: #6d9cbe;">$i</span><span style="color: #e0882f;">++;</span>
<a style="color: #1299da; text-decoration: none;" href="http://www.php.net/echo"><span style="color: #e2392d;">echo</span></a> <span style="color: #6d9cbe;">$i</span><span style="color: #e0882f;">;</span></pre>
<p style="text-indent: 2em;">咱们先不论答案是什么？我们直接从Zend内核查看这种自增操作的实现。</p>
<p style="text-indent: 2em;">使用VLD查看包含了$i++和++$i的PHP代码生成的中间代码：</p>
<pre style="background-color: #333333; color: #ffffff; font: normal normal normal 13px/normal 'Bitstream Vera Sans Mono', 'DejaVu Sans Mono', 'Courier New', monospace; overflow-x: auto; overflow-y: auto; padding: 10px;"><span style="color: #6d9cbe;">$i</span> <span style="color: #e0882f;">=</span> <span style="color: #1299da;">0</span><span style="color: #e0882f;">;</span>
<span style="color: #6d9cbe;">$i</span><span style="color: #e0882f;">++;</span>
<span style="color: #e0882f;">++</span><span style="color: #6d9cbe;">$i</span><span style="color: #e0882f;">;</span></pre>
<p style="text-indent: 2em;"><a style="color: #1299da; text-decoration: underline;" href="http://www.phppan.com/2011/05/vld-extension/">使用VLD命令</a>(php -dvld.active=1 -dvld.verbosity=3 t.php)查看详细参数:</p>
<pre style="background-color: #333333; color: #ffffff; font: normal normal normal 13px/normal 'Bitstream Vera Sans Mono', 'DejaVu Sans Mono', 'Courier New', monospace; overflow-x: auto; overflow-y: auto; padding: 10px;">number of ops:  8
compiled vars:  !0 = $i
line     # *  op                           fetch          ext  return  operands
--------------------------------------------------------------------------------
-
   2     0  &gt;   EXT_STMT                                          RES[  IS_UNUSED  ]         OP1[  IS_UNUSED  ] OP2[  IS_UNUSED  ]
         1      ASSIGN                                                    OP1[IS_CV !0 ] OP2[ ,  IS_CONST (0) 0 ]
   3     2      EXT_STMT                                          RES[  IS_UNUSED  ]         OP1[  IS_UNUSED  ] OP2[  IS_UNUSED  ]
         3      POST_INC                                          RES[  IS_TMP_VAR ~1 ]       OP1[  IS_CV !0 ]
         4      FREE                                                      OP1[IS_TMP_VAR ~1 ]
   4     5      EXT_STMT                                          RES[  IS_UNUSED  ]         OP1[  IS_UNUSED  ] OP2[  IS_UNUSED  ]
         6      PRE_INC                                                   OP1[IS_CV !0 ]
   5     7    &gt; RETURN                                                    OP1[IS_CONST (0) 1 ]

branch: #  0; line:     2-    5; sop:     0; eop:     7
path #1: 0,</pre>
<p style="text-indent: 2em;">从VLD扩展的输出信息可以知道，前缀自增(++$i)对应的opcode为PRE_INC，后缀自增($i++)对应的opcode为POST_INC。 首先我们看前缀自增(++$i)，++$i没有返回值或者说它的返回值为空。 根据中间代码和VLD显示的OP1的参数类型， 我们可以知道++$i的中间代码在执行是最终调用的是Zend/zend_vm_execute.h文件中的ZEND_PRE_INC_SPEC_CV_HANDLER函数。 在ZEND_PRE_INC_SPEC_CV_HANDLER函数中有几个关键点:</p>
<ul>
<li>CV类型变量的获取，它是调用_get_zval_ptr_ptr_cv获取CV类型变量。 这里的CV类型的变量是PHP编译期间的类似于缓存的作用，主要作用是提高某些变量的存储速度。</li>
<li>increment_function函数，不管是实例变量，类变量或者常规的变量，最终都是调用increment_function函数实现变量的增加操作。 在这个函数中，程序会根据变量的类型做出不同的处理，在PHP5.3.1这个版本中，PHP支持IS_LONG、IS_DOUBLE、IS_NULL和IS_STRING四种类型。 如果变量的类型是IS_NULL，程序会将变量的值赋值为1。如果变量类型是字符串，程序会将其转化成整形或浮点型进行计算。</li>
<li>使用RETURN_VALUE_UNUSED宏清除返回结果，这个宏的作用是将result变量的类型设置为EXT_TYPE_UNUSED类型。</li>
</ul>
<p style="text-indent: 2em;">前缀自增(++$i)操作在Zend内核中本质上是操作变量本身，而且在表达式中使用的也是这个变量本身。</p>
<p style="text-indent: 2em;">了解了++$i的实现，我们来看下可能使用得更多的$i++操作的实现。 同样，从中间代码POST_INC和OP1的类型是IS_CV，我们可以在Zend/zend_vm_execute.h文件中找到其实现为ZEND_POST_INC_SPEC_CV_HANDLER。 与前面的ZEND_PRE_INC_SPEC_CV_HANDLER相比，它们都有一个取CV类型变量的过程，也有一个increment_function函数增加变量值的过程， 但是除此之外它多了一个操作，同时也少了一个操作。 它多的一个操作是：</p>
<pre style="background-color: #333333; color: #ffffff; font: normal normal normal 13px/normal 'Bitstream Vera Sans Mono', 'DejaVu Sans Mono', 'Courier New', monospace; overflow-x: auto; overflow-y: auto; padding: 10px;">EX_T<span style="color: #ffffff;">(</span>opline<span style="color: #e0882f;">-&gt;</span>result.<span style="color: #ffffff;">u</span>.<span style="color: #ffffff;">var</span><span style="color: #ffffff;">)</span>.<span style="color: #ffffff;">tmp_var</span> <span style="color: #e0882f;">=</span> <span style="color: #e0882f;">**</span>var_ptr<span style="color: #e0882f;">;</span>
zendi_zval_copy_ctor<span style="color: #ffffff;">(</span>EX_T<span style="color: #ffffff;">(</span>opline<span style="color: #e0882f;">-&gt;</span>result.<span style="color: #ffffff;">u</span>.<span style="color: #ffffff;">var</span><span style="color: #ffffff;">)</span>.<span style="color: #ffffff;">tmp_var</span><span style="color: #ffffff;">)</span><span style="color: #e0882f;">;</span></pre>
<p style="text-indent: 2em;">这两行代码的作用是初始化返回值到临时变量，并且将原始的$i的值存储在这，这就是我们在前面使用VLD查看生成的中间代码其结果为RES[ IS_TMP_VAR ~1 ]的原因。 在这个初始化完成后，程序会继续执行增加操作，在增加操作完成后，它就结束了，而之前的++$i操作则会将result设置为UNUSED类型，这就是它少的那个操作。</p>
<p style="text-indent: 2em;">后缀自增($i++)在表达式中使用的是存放在临时变量中原先的变量值，而变量本身的值已经增加了。 在PHP中这种变量的分离是通过临时变量+返回值解决。</p>
<p style="text-indent: 2em;">到这里，我们可以回答最开始的问题了，它会输出0。因为在表达式中$i++的返回值是一个临时变量，也就是$i原来的值，也就是0。</p>
]]></content:encoded>
			<wfw:commentRss>https://www.phppan.com/2011/05/pre_inc-and-post_inc-in-php/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>深入理解PHP之引用一</title>
		<link>https://www.phppan.com/2011/03/phparch-php-variables-article-1/</link>
		<comments>https://www.phppan.com/2011/03/phparch-php-variables-article-1/#comments</comments>
		<pubDate>Tue, 08 Mar 2011 02:22:52 +0000</pubDate>
		<dc:creator><![CDATA[admin]]></dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[refcount]]></category>
		<category><![CDATA[变量]]></category>
		<category><![CDATA[引用]]></category>
		<category><![CDATA[引用计数]]></category>

		<guid isPermaLink="false">http://www.phppan.com/?p=1300</guid>
		<description><![CDATA[深入理解PHP之引用一 作者Derick Rethans 译者：Martin Pan&#60;http://ww [&#8230;]]]></description>
				<content:encoded><![CDATA[<p align="center"><strong>深入理解PHP之引用一</strong></p>
<p align="right">作者Derick Rethans</p>
<p align="right">译者：Martin Pan&lt;http://www.phppan.com/&gt;</p>
<p>PHP是弱语言，其变量处理的过程是不可见的。</p>
<p>你是否曾经很想知道在变量拷贝的时候，PHP引擎做了什么？</p>
<p>你是否曾经很想知道一个函数是如何以引用的方式返回一个变量？</p>
<p>如果是这样，请您接着向下看。</p>
<p>每门计算机语言都需要一些容器来保存变量数据。在一些语言当中，变量都有特定的类型，如字符串，数组，对象等等。比如C和Pascal就属于这种。而PHP则没有这样的类型。在PHP中，一个变量在某一行是字符串，可能到下一行就变成了数字。变量可以经常在不同的类型间轻易的转化，甚至是自动的转换。PHP之所以成为一个简单并且强大的语言，很大一部分的原因是它拥有弱类型的变量。但是有些时候这也会带来一些有趣的问题。</p>
<p>在PHP内部，变量是存储在一个叫做zval的容器中。它不仅仅包含变量的值，也包含变量的类型。Python和PHP类似，也有一个标签标记变量类型。变量容器中包含一些Zend引擎用来区分是否引用的字段。同时它也包含这个值的引用计数。</p>
<p>变量存储在一个相当于关联数组的符号表中。这个数组以变量名为key,并且指向包含了这些变量的容器。如图1所示：</p>
<p><a href="http://www.phppan.com/wp-content/uploads/2011/03/php-variables-01.png"><img class="aligncenter size-full wp-image-1302" title="php-variables-01" src="http://www.phppan.com/wp-content/uploads/2011/03/php-variables-01.png" alt="php-variables-01" width="756" height="410" /></a></p>
<h2>引用计数</h2>
<p align="left">PHP试着在变量拷贝(如 $a = $b )的时候变得聪明些。“=”也称为赋值操作符。当进行赋值操作时，Zend引擎不会创建一个新的变量窗口，而是增大变量窗口的 refcount 字段，你可以想象一下，当这个变量是一个巨大的字符串或一个巨大 的数组时，这将节约多少的内存。如图2所示，</p>
<p style="text-align: center;" align="left"><a href="http://www.phppan.com/wp-content/uploads/2011/03/php-variables-02.png"><img class="aligncenter size-full wp-image-1303" title="php-variables-02" src="http://www.phppan.com/wp-content/uploads/2011/03/php-variables-02.png" alt="php-variables-02" width="646" height="896" /></a></p>
<p>第一步： 变量a,包含文本”this is”。默认情况下，引用计数等于1</p>
<p align="left">第二步：将变量$a赋值给$b和$c。这里没有新的变量容器生成，仅仅是每次在变量赋值操作时将refcount加1。因为这里执行了两次赋值操作，所以refcount最后会变成3。</p>
<p align="left">现在，也许你很想知道当变量$c改变时将发生什么。根据refcount的值的不同，它会有两种不同的处理方式。如果refcount等于1，这个变量容器将更新它的值（也许同时会更新它的类型）。如果refcount大于1，将创建一个包含了新值（和类型）的变量容器。如图2所示的第三步，$a变量所在的变量容器的refcount值被减去一，现在refcount的值是2，而新创建的容器的refcount的值为1。当对一个变量使用unset函数时，这个变量所在的容器的refcount值将减去一，如图第4步所示。如果refcount的值少于1，Zend引擎将翻译这个变量容器，如图第5步所示。</p>
<p align="left">
<h2>传递变量给函数（Passing Variables to Functions）</h2>
<p align="left">除了所有脚本共用的全局符号表以外，每个用户定义的函数在调用时都会创建一个属于自己的符号表，用来存放它自己的变量。当一个函数被调用后，Zend引擎就会创建一个这样的符号表，当这个函数返回时这个函数表就会被释放。一个函数要么通过return语句返回，要么因为函数结束而返回(译者注：无返回的函数默认会返回NULL)。如图3所示：</p>
<p align="left">
<p style="text-align: center;" align="left"><a href="http://www.phppan.com/wp-content/uploads/2011/03/php-variables-03.png"><img class="aligncenter size-large wp-image-1304" title="php-variables-03" src="http://www.phppan.com/wp-content/uploads/2011/03/php-variables-03-1024x684.png" alt="php-variables-03" width="717" height="479" /></a></p>
<p align="left">图3详细介绍了变量是如何传递给函数的。</p>
<p align="left">第一步,我们将”thisis”赋给变量$a，然后我们将这个变量传递do_something()函数的$s变量。</p>
<p align="left">第二步，你可以看到这与变量赋值的操作是一样的（与我们在前一小节提到的$b = $a类似），只是其存储在不同的符号表（函数符号表），并且引用计数加2，而不是加1。原因是函数栈也包含了这个变量容器的引用。</p>
<p align="left">第三步，当我们赋新值给变量$s，原变量容器的refcount减1，并且创建一个包含了新值的变量容器。</p>
<p>第四步，我们通过return语句返回一个变量。返回的变量从全局符号表中获取一个实体并将其refcount的值增加1.当函数结束时，函数的符号表将被销毁。在销毁的过程中，Zend引擎将遍历符号表中的每个变量，并将其refcount的值减少。当变量容器的refount的值变为0,这个变量容器将会被销毁。如你所见，由于 PHP的引用计数机制，变量容器不是以拷贝的方式从函数返回。如果变量$s在第三步时没有被修改，则变量$a和$b将一直指向相同的变量容器（这个容器的refcount为2）。在这种情况下，语句$a = “this is”将不会创建变量容器的副本。</p>
<p>英文原文地址：http://derickrethans.nl/files/phparch-php-variables-article.pdf</p>
<p>以上只是第一部分的内容，原来看懂很容易，翻译出来相当难。</p>
]]></content:encoded>
			<wfw:commentRss>https://www.phppan.com/2011/03/phparch-php-variables-article-1/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>PHP的Socket编程</title>
		<link>https://www.phppan.com/2011/02/php-socket/</link>
		<comments>https://www.phppan.com/2011/02/php-socket/#comments</comments>
		<pubDate>Mon, 21 Feb 2011 01:10:33 +0000</pubDate>
		<dc:creator><![CDATA[admin]]></dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[socket]]></category>
		<category><![CDATA[进程通信]]></category>

		<guid isPermaLink="false">http://www.phppan.com/?p=1268</guid>
		<description><![CDATA[PHP的Socket编程 计算机进程可以使用socket和其他进程通信，通过socket，其他进程的位置是透明 [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>PHP的Socket编程</p>
<p>计算机进程可以使用socket和其他进程通信，通过socket，其他进程的位置是透明的。这些进程可以在同一台计算机上也可以在不同的计算机上。</p>
<p>在PHP中，socket是以扩展的方式加载的，如果无法使用socket相关函数，请确认是否有打开此扩展。<br />
下面我们以一个面向连接的客户端和服务器的简单实现说明一些函数的使用，在此之后，简单介绍在PHP的内部是如何实现这些函数的。</p>
<p><strong>【客户端实现】</strong><br />
如下所示代码为客户端的实现代码：</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="php" style="font-family:monospace;"><span style="color: #990000;">set_time_limit</span><span style="color: #009900;">&#40;</span><span style="color: #cc66cc;">0</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #000088;">$host</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">&quot;127.0.0.1&quot;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$port</span> <span style="color: #339933;">=</span> <span style="color: #cc66cc;">2046</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #000088;">$socket</span> <span style="color: #339933;">=</span> <span style="color: #990000;">socket_create</span><span style="color: #009900;">&#40;</span>AF_INET<span style="color: #339933;">,</span> SOCK_STREAM<span style="color: #339933;">,</span> SOL_TCP<span style="color: #009900;">&#41;</span>or <span style="color: #990000;">die</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;Could not create	socket<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #666666; font-style: italic;">// 创建一个Socket</span>
&nbsp;
<span style="color: #000088;">$connection</span> <span style="color: #339933;">=</span> <span style="color: #990000;">socket_connect</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$socket</span><span style="color: #339933;">,</span> <span style="color: #000088;">$host</span><span style="color: #339933;">,</span> <span style="color: #000088;">$port</span><span style="color: #009900;">&#41;</span> or <span style="color: #990000;">die</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;Could not connet server<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>    <span style="color: #666666; font-style: italic;">//  连接</span>
&nbsp;
<span style="color: #990000;">socket_write</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$socket</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">&quot;time&quot;</span><span style="color: #009900;">&#41;</span> or <span style="color: #990000;">die</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;Write failed<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #666666; font-style: italic;">// 数据传送 向服务器发送消息</span>
&nbsp;
<span style="color: #b1b100;">while</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$buffer</span> <span style="color: #339933;">=</span> <span style="color: #990000;">socket_read</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$socket</span><span style="color: #339933;">,</span> <span style="color: #cc66cc;">1024</span><span style="color: #339933;">,</span> PHP_NORMAL_READ<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #b1b100;">echo</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;Data sent was: time<span style="color: #000099; font-weight: bold;">\n</span>Response was:&quot;</span> <span style="color: #339933;">.</span> <span style="color: #000088;">$buffer</span> <span style="color: #339933;">.</span> <span style="color: #0000ff;">&quot;<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #990000;">socket_close</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$socket</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></td></tr></table></div>

<p>客户端首先创建一个socket，并且连接服务器。向服务器发送一个time的消息，等待服务器返回信息，读取服务器的信息并输出。</p>
<p><strong>【服务器实现】</strong></p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="php" style="font-family:monospace;">&nbsp;
<span style="color: #990000;">set_time_limit</span><span style="color: #009900;">&#40;</span><span style="color: #cc66cc;">0</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #000088;">$host</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">&quot;127.0.0.1&quot;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$port</span> <span style="color: #339933;">=</span> <span style="color: #cc66cc;">2046</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #000088;">$socket</span> <span style="color: #339933;">=</span> <span style="color: #990000;">socket_create</span><span style="color: #009900;">&#40;</span>AF_INET<span style="color: #339933;">,</span> SOCK_STREAM<span style="color: #339933;">,</span> SOL_TCP<span style="color: #009900;">&#41;</span> or <span style="color: #990000;">die</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;Could not create	socket<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #666666; font-style: italic;">// 创建一个Socket</span>
&nbsp;
<span style="color: #000088;">$result</span> <span style="color: #339933;">=</span> <span style="color: #990000;">socket_bind</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$socket</span><span style="color: #339933;">,</span> <span style="color: #000088;">$host</span><span style="color: #339933;">,</span> <span style="color: #000088;">$port</span><span style="color: #009900;">&#41;</span> or <span style="color: #990000;">die</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;Could not bind tosocket<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #666666; font-style: italic;">//绑定Socket到端口</span>
&nbsp;
<span style="color: #000088;">$result</span> <span style="color: #339933;">=</span> <span style="color: #990000;">socket_listen</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$socket</span><span style="color: #339933;">,</span> <span style="color: #cc66cc;">3</span><span style="color: #009900;">&#41;</span> or <span style="color: #990000;">die</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;Could not set up socket listener<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #666666; font-style: italic;">// 开始监听连接</span>
&nbsp;
<span style="color: #000088;">$spawn</span> <span style="color: #339933;">=</span> <span style="color: #990000;">socket_accept</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$socket</span><span style="color: #009900;">&#41;</span> or <span style="color: #990000;">die</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;Could not accept incoming connection<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #666666; font-style: italic;">// 处理通信</span>
&nbsp;
<span style="color: #000088;">$input</span> <span style="color: #339933;">=</span> <span style="color: #990000;">socket_read</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$spawn</span><span style="color: #339933;">,</span> <span style="color: #cc66cc;">1024</span><span style="color: #009900;">&#41;</span> or <span style="color: #990000;">die</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;Could not read input<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #666666; font-style: italic;">// 数据传送 获得客户端的输入</span>
&nbsp;
<span style="color: #000088;">$input</span> <span style="color: #339933;">=</span> <span style="color: #990000;">trim</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$input</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #b1b100;">echo</span> <span style="color: #0000ff;">'input:'</span><span style="color: #339933;">,</span> <span style="color: #000088;">$input</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">&quot;<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$input</span> <span style="color: #339933;">==</span> <span style="color: #0000ff;">'time'</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #000088;">$output</span> <span style="color: #339933;">=</span> <span style="color: #990000;">date</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;Y-m-d H:i:s&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">.</span> <span style="color: #0000ff;">&quot;<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #339933;">;</span> <span style="color: #666666; font-style: italic;">//处理客户端输入并返回结果</span>
<span style="color: #009900;">&#125;</span><span style="color: #b1b100;">else</span><span style="color: #009900;">&#123;</span>
    <span style="color: #000088;">$output</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">&quot;input error <span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #339933;">;</span> <span style="color: #666666; font-style: italic;">//处理客户端输入并返回结果</span>
<span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #b1b100;">echo</span> <span style="color: #0000ff;">&quot;output:&quot;</span><span style="color: #339933;">,</span> <span style="color: #000088;">$output</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">&quot;<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">//	数据传送 向客户端写入返回结果</span>
<span style="color: #990000;">socket_write</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$spawn</span><span style="color: #339933;">,</span> <span style="color: #000088;">$output</span><span style="color: #339933;">,</span> <span style="color: #990000;">strlen</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$output</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> or <span style="color: #990000;">die</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;Could not write output<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>	
&nbsp;
<span style="color: #666666; font-style: italic;">// 关闭sockets</span>
<span style="color: #990000;">socket_close</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$spawn</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #990000;">socket_close</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$socket</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></td></tr></table></div>

<p>服务器端创建一个socket，并且绑定端口，监听连接，读取客户端的数据，根据客户端的输入返回不同的值，最后写入数据到客户端。关闭socket。<br />
只是这个服务器不能接受多个连接并且只完成一个操作<br />
<strong>【PHP内部源码说明】</strong><br />
从PHP内部源码来看，PHP提供的socket编程是在socket，bind,listen等函数外添加了一个层，让其更加简单和方便调用。但是一些业务逻辑的程序还是需要程序员自己去实现。<br />
下面我们以socket_create的源码实现来说明PHP的内部实现。<br />
前面我们有说到php的socket是以扩展的方式实现的。在源码的ext目录，我们找到sockets目录。这个目录存放了PHP对于socket的实现。直接搜索PHP_FUNCTION(socket_create)，在sockets.c文件中找到了此函数的实现。如下所示代码：</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="c" style="font-family:monospace;"><span style="color: #808080; font-style: italic;">/* {{{ proto resource socket_create(int domain, int type, int protocol) U
   Creates an endpoint for communication in the domain specified by domain, of type specified by type */</span>
PHP_FUNCTION<span style="color: #009900;">&#40;</span>socket_create<span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
        <span style="color: #993333;">long</span>            arg1<span style="color: #339933;">,</span> arg2<span style="color: #339933;">,</span> arg3<span style="color: #339933;">;</span>
        php_socket      <span style="color: #339933;">*</span>php_sock <span style="color: #339933;">=</span> <span style="color: #009900;">&#40;</span>php_socket<span style="color: #339933;">*</span><span style="color: #009900;">&#41;</span>emalloc<span style="color: #009900;">&#40;</span><span style="color: #993333;">sizeof</span><span style="color: #009900;">&#40;</span>php_socket<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
        <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span>zend_parse_parameters<span style="color: #009900;">&#40;</span>ZEND_NUM_ARGS<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> TSRMLS_CC<span style="color: #339933;">,</span> <span style="color: #ff0000;">&quot;lll&quot;</span><span style="color: #339933;">,</span> <span style="color: #339933;">&amp;</span>arg1<span style="color: #339933;">,</span> <span style="color: #339933;">&amp;</span>arg2<span style="color: #339933;">,</span> <span style="color: #339933;">&amp;</span>arg3<span style="color: #009900;">&#41;</span> <span style="color: #339933;">==</span> FAILURE<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
                efree<span style="color: #009900;">&#40;</span>php_sock<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
                <span style="color: #b1b100;">return</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>
&nbsp;
        <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span>arg1 <span style="color: #339933;">!=</span> AF_UNIX
<span style="color: #339933;">#if HAVE_IPV6</span>
                <span style="color: #339933;">&amp;&amp;</span> arg1 <span style="color: #339933;">!=</span> AF_INET6
<span style="color: #339933;">#endif</span>
                <span style="color: #339933;">&amp;&amp;</span> arg1 <span style="color: #339933;">!=</span> AF_INET<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
                php_error_docref<span style="color: #009900;">&#40;</span>NULL TSRMLS_CC<span style="color: #339933;">,</span> E_WARNING<span style="color: #339933;">,</span> <span style="color: #ff0000;">&quot;invalid socket domain [%ld] specified for argument 1, assuming AF_INET&quot;</span><span style="color: #339933;">,</span> arg1<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
                arg1 <span style="color: #339933;">=</span> AF_INET<span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>
&nbsp;
        <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span>arg2 <span style="color: #339933;">&gt;</span> <span style="color: #0000dd;">10</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
                php_error_docref<span style="color: #009900;">&#40;</span>NULL TSRMLS_CC<span style="color: #339933;">,</span> E_WARNING<span style="color: #339933;">,</span> <span style="color: #ff0000;">&quot;invalid socket type [%ld] specified for argument 2, assuming SOCK_STREAM&quot;</span><span style="color: #339933;">,</span> arg2<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
                arg2 <span style="color: #339933;">=</span> SOCK_STREAM<span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>
&nbsp;
        php_sock<span style="color: #339933;">-&gt;</span>bsd_socket <span style="color: #339933;">=</span> socket<span style="color: #009900;">&#40;</span>arg1<span style="color: #339933;">,</span> arg2<span style="color: #339933;">,</span> arg3<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        php_sock<span style="color: #339933;">-&gt;</span>type <span style="color: #339933;">=</span> arg1<span style="color: #339933;">;</span>
&nbsp;
        <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span>IS_INVALID_SOCKET<span style="color: #009900;">&#40;</span>php_sock<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
                SOCKETS_G<span style="color: #009900;">&#40;</span>last_error<span style="color: #009900;">&#41;</span> <span style="color: #339933;">=</span> errno<span style="color: #339933;">;</span>
                php_error_docref<span style="color: #009900;">&#40;</span>NULL TSRMLS_CC<span style="color: #339933;">,</span> E_WARNING<span style="color: #339933;">,</span> <span style="color: #ff0000;">&quot;Unable to create socket [%d]: %s&quot;</span><span style="color: #339933;">,</span> errno<span style="color: #339933;">,</span> php_strerror<span style="color: #009900;">&#40;</span>errno TSRMLS_CC<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
                efree<span style="color: #009900;">&#40;</span>php_sock<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
                RETURN_FALSE<span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>
&nbsp;
        php_sock<span style="color: #339933;">-&gt;</span>error <span style="color: #339933;">=</span> <span style="color: #0000dd;">0</span><span style="color: #339933;">;</span>
        php_sock<span style="color: #339933;">-&gt;</span>blocking <span style="color: #339933;">=</span> <span style="color: #0000dd;">1</span><span style="color: #339933;">;</span>
                                                                                                                                           <span style="color: #0000dd;">1257</span><span style="color: #339933;">,</span><span style="color: #0000dd;">1</span><span style="color: #339933;">-</span><span style="color: #0000dd;">8</span>      <span style="color: #0000dd;">61</span><span style="color: #339933;">%</span>
        ZEND_REGISTER_RESOURCE<span style="color: #009900;">&#40;</span>return_value<span style="color: #339933;">,</span> php_sock<span style="color: #339933;">,</span> le_socket<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>
<span style="color: #808080; font-style: italic;">/* }}} */</span></pre></td></tr></table></div>

<p>从整个函数的实现看，程序基本上是一个错误和异常处理。PHP本身引入了php_socket结构体，其创建时调用socket函数实现。</p>
<p>PS:关于PHP的网络编程，我们会在TIPI系列文章中作详细的说明。<br />
<strong>【socket函数】</strong><br />
函数名      描述<br />
socket_accept()    接受一个Socket连接<br />
socket_bind()     把socket绑定在一个IP地址和端口上<br />
socket_clear_error()   清除socket的错误或最后的错误代码<br />
socket_close()     关闭一个socket资源<br />
socket_connect()    开始一个socket连接<br />
socket_create_listen()   在指定端口打开一个socket监听<br />
socket_create_pair()   产生一对没有差别的socket到一个数组里<br />
socket_create()    产生一个socket，相当于产生一个socket的数据结构<br />
socket_get_option()    获取socket选项<br />
socket_getpeername()   获取远程类似主机的ip地址<br />
socket_getsockname()   获取本地socket的ip地址<br />
socket_iovec_add()    添加一个新的向量到一个分散/聚合的数组<br />
socket_iovec_alloc()   这个函数创建一个能够发送接收读写的iovec数据结构<br />
socket_iovec_delete()   删除一个已分配的iovec<br />
socket_iovec_fetch()   返回指定的iovec资源的数据<br />
socket_iovec_free()    释放一个iovec资源<br />
socket_iovec_set()    设置iovec的数据新值<br />
socket_last_error()    获取当前socket的最后错误代码<br />
socket_listen()     监听由指定socket的所有连接<br />
socket_read()     读取指定长度的数据<br />
socket_readv()     读取从分散/聚合数组过来的数据<br />
socket_recv()     从socket里结束数据到缓存<br />
socket_recvfrom()    接受数据从指定的socket，如果没有指定则默认当前socket<br />
socket_recvmsg()    从iovec里接受消息<br />
socket_select()     多路选择<br />
socket_send()     这个函数发送数据到已连接的socket<br />
socket_sendmsg()    发送消息到socket<br />
socket_sendto()    发送消息到指定地址的socket<br />
socket_set_block()    在socket里设置为块模式<br />
socket_set_nonblock()   socket里设置为非块模式<br />
socket_set_option()    设置socket选项<br />
socket_shutdown()    这个函数允许你关闭读、写、或指定的socket<br />
socket_strerror()    返回指定错误号的周详错误<br />
socket_write()     写数据到socket缓存<br />
socket_writev()    写数据到分散/聚合数组</pre>
</pre>
]]></content:encoded>
			<wfw:commentRss>https://www.phppan.com/2011/02/php-socket/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>思考PHP语言四：接口和抽象类</title>
		<link>https://www.phppan.com/2010/12/thinkinphp-4-interface-abstract-class/</link>
		<comments>https://www.phppan.com/2010/12/thinkinphp-4-interface-abstract-class/#comments</comments>
		<pubDate>Fri, 24 Dec 2010 02:35:50 +0000</pubDate>
		<dc:creator><![CDATA[admin]]></dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[思考PHP语言]]></category>
		<category><![CDATA[抽象类]]></category>
		<category><![CDATA[接口]]></category>

		<guid isPermaLink="false">http://www.phppan.com/?p=1197</guid>
		<description><![CDATA[思考PHP语言四：接口和抽象类 【概述】 在写PHP的日子里，我们多是按照需求完成相关功能，对于一些设计的工作 [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>思考PHP语言四：接口和抽象类<br />
<strong>【概述】</strong><br />
在写PHP的日子里，我们多是按照需求完成相关功能，对于一些设计的工作较少的接触，也许是PHP的历史遗留问题或者其它，对于PHP的接口与抽象类使用得较少，但是对于一个支持面向对象的语言，接口与抽象是两个非常重要的内容。这里我们介绍接口与抽象类的一些基础知识，思考一些关于面向对象的东西。<br />
<strong>【接口】</strong><br />
接口是一些方法特征的集合，这里的方法没有实现，只有声明。如果一个类继承了某个接口，则需要实现这个接口的所有方法。接口除了声明方法外，还可以定义常量。如下所示：</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
</pre></td><td class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">interface</span> IFoo <span style="color: #009900;">&#123;</span>
	<span style="color: #000000; font-weight: bold;">const</span> CONST_VAR <span style="color: #339933;">=</span> <span style="color: #0000ff;">'martin'</span><span style="color: #339933;">;</span>
	<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> method<span style="color: #009900;">&#40;</span><span style="color: #000088;">$str</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></td></tr></table></div>

<p>接口中方法的声明需要包含方法的名称，参数。不用包含参数类型和返还类型（PHP的函数本来就不用定义参数类型和返还类型）。<br />
接口的方法只能是public，这说明接口本身包含的对外开放的意义在访问控制中体现出来了，并且当我们实现接口的方法时，也不能修改方法的访问控制权限。</p>
<p>接口是可以继承的，接口可以继承接口(和类继承一样，使用extends关键字)，类可以继承接口（我们称之为接口继承，用implements关键字）</p>
<p>实现同一个接口的两个类可能功能完全不同，但是他们有相同的方法以及方法参数，并且都是公开的，从而他们可以提供相类似的服务，从而具有相同的接口。</p>
<p><strong>接口的可插入性</strong><br />
在一个拥有多个层次结构的类组织中，如果要给某个处于中间位置的类添加父类，如果我们没有接口，则我们需要修改这个类的所有父类，打乱整个类的层次结构。当有了接口后，任何一个类都可以实现一个接口，此时，接口不会影响父类，但是会影响所有的子类，此类将必须实现这个接口的所有方法（抽象类可以不用实现所有方法，只是将实现下移到子类），子类则可以自动从此类继承实现后的方法。这就是接口的可插入性。</p>
<p>接口通常被用来声明一个新的类型，并且会作为一个类组织结构的起点，特别是当某个实体属于多个类型时，此时接口的作用就体现出来了。另外，理想情况下（现实中没发现过）一个类只应该实现接口或抽象类所声明的方法，纯理想呵。</p>
<p><strong>【抽象类】</strong><br />
抽象类是类的一种，通过在类定义前添加abstract关键字实现。如下示例：</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
</pre></td><td class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">abstract</span> <span style="color: #000000; font-weight: bold;">class</span> AbstarctFoo <span style="color: #009900;">&#123;</span>
	<span style="color: #000000; font-weight: bold;">abstract</span> <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> method<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></td></tr></table></div>

<p>抽象类不能实例化，一般作为类组织结构中枝节点或根节点存在。<br />
抽象类提供一个类型的部分实现，抽象类可以有实例变量，可以有构造方法，可以有抽象方法，同时也可以有具体的方法实现。抽象类的构造方法可以被子类调用，只是需要显式调用。<br />
我们在做设计时需要注意的是一般不要从具体类继承，具体类是用来实例化的。<br />
在类的组织结构中，一般抽象类是枝节点，具体类是叶节点，在设计结构时应该尽量将公共代码放到作为父类的抽象类中，这样可以提高代码的复用性，与公共代码的移动相反，数据应该尽量放到具体类。<br />
在继承过程中，子类的责任是扩展父类，而不是置换或取消掉父类的职责，当有取消或置换父类的职责的情况发生时，此时可能你的设计有问题了，需要考虑他们是否是is-a的关系？<br />
<strong>抽象类和接口有相同的方法时</strong><br />
在PHP中，如果一个类继承了一个抽象类并且实现了一个接口，如果此时这个抽象类和接口中有相同名称的方法，则此时对于接口的实现会报错。与此相同，当一个抽象类实现一个接口时，如果接口已经声明了方法A，则在抽象方法中将不能再次声明此方法。</p>
]]></content:encoded>
			<wfw:commentRss>https://www.phppan.com/2010/12/thinkinphp-4-interface-abstract-class/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>思考PHP语言三：异常处理</title>
		<link>https://www.phppan.com/2010/12/thinkinphp-3-exception/</link>
		<comments>https://www.phppan.com/2010/12/thinkinphp-3-exception/#comments</comments>
		<pubDate>Wed, 22 Dec 2010 01:28:03 +0000</pubDate>
		<dc:creator><![CDATA[admin]]></dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[异常处理]]></category>
		<category><![CDATA[思考PHP语言]]></category>
		<category><![CDATA[断言]]></category>

		<guid isPermaLink="false">http://www.phppan.com/?p=1192</guid>
		<description><![CDATA[思考PHP语言三：异常处理 【概述】 异常处理是指在语言中能够使程序按照一种标准的方法对于某些运行时错误和其他 [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>思考PHP语言三：异常处理<br />
<strong>【概述】</strong><br />
异常处理是指在语言中能够使程序按照一种标准的方法对于某些运行时错误和其他程序所检测到的异常事件做出反应。异常发生的时间是不可以确定的，如果一种语言不包括异常处理机制，这就会给语言带来额外的复杂性。<br />
一般来说，对于异常的处理有三种方案：<br />
1、将一个额外的参数作为状态变量，通过标记这个状态值判断是否发生了异常。在C的标准库中许多函数使用返回值作为出错的状态变量。<br />
2、将一个标号参数传给子程序，当异常发生时，通过标号将程序调用跳转到程序中的不同位置<br />
3、将一个异常处理独立出来，作为专门的子程序或类存在。</p>
<p>在基于C的语言中，将异常出现称之为thrown，而不是raise，是因为在标准的C程序库中已经存在一个叫做raise的函数。<br />
在PHP5中使用第3种方式。<br />
<strong>【PHP中的异常处理】</strong><br />
在PHP5以后，PHP添加了异常处理模块。PHP的异常处理模块与java有一些类似，异常可被 throw 语句抛出并被 catch 语句捕获。需要进行异常处理的代码都必须放入 try 代码块内，以便捕获可能存在的异常。每一个 try 至少要有一个与之对应的 catch。使用多个 catch 可以捕获不同的类所产生的异常(嗯，这里没有throws子句)。当 try 代码块不再抛出异常或者找不到 catch 能匹配所抛出的异常时，PHP 代码就会在跳转到最后一个 catch 的后面继续执行。所以在安排catch的顺序时，需要将详细或子类的异常类放到前面。在有一些情况下，不管try子句是否抛出异常，也不管是否捕获了异常，程序都要执行一个过程，此时我们就需要finally子句，只是在PHP中并没有finally子句（HOHO）。<br />
一个异常的简单示例：</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
</pre></td><td class="code"><pre class="php" style="font-family:monospace;">try <span style="color: #009900;">&#123;</span>
	<span style="color: #b1b100;">throw</span> <span style="color: #000000; font-weight: bold;">new</span> Exception<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;error msg&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>catch<span style="color: #009900;">&#40;</span>Exception <span style="color: #000088;">$e</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
	 <span style="color: #b1b100;">echo</span> <span style="color: #0000ff;">'Caught exception: '</span><span style="color: #339933;">,</span>  <span style="color: #000088;">$e</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getMessage</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">&quot;<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></td></tr></table></div>

<p>PHP提供了Exception类，以及在SPL中提供了一些内置的异常类，我们可以通过继承Exception类而实现属于自己的异常类。在一个面向对象系统的设计中我们需要考虑关于错误的处理情况，是以PHP的内部错误报告，还是以异常的方式给出，此时我们需要规划一套专属于我们系统的异常子系统。并且对于PHP的内部错误报告我们可以使用ErrorException进行转换，如下所示帮助文档中的代码：</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
</pre></td><td class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">function</span> exception_error_handler<span style="color: #009900;">&#40;</span><span style="color: #000088;">$errno</span><span style="color: #339933;">,</span> <span style="color: #000088;">$errstr</span><span style="color: #339933;">,</span> <span style="color: #000088;">$errfile</span><span style="color: #339933;">,</span> <span style="color: #000088;">$errline</span> <span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #b1b100;">throw</span> <span style="color: #000000; font-weight: bold;">new</span> ErrorException<span style="color: #009900;">&#40;</span><span style="color: #000088;">$errstr</span><span style="color: #339933;">,</span> <span style="color: #cc66cc;">0</span><span style="color: #339933;">,</span> <span style="color: #000088;">$errno</span><span style="color: #339933;">,</span> <span style="color: #000088;">$errfile</span><span style="color: #339933;">,</span> <span style="color: #000088;">$errline</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>
<span style="color: #990000;">set_error_handler</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;exception_error_handler&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">/* Trigger exception */</span>
<span style="color: #990000;">strpos</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></td></tr></table></div>

<p><strong>【断言】</strong><br />
断言常常被用于防错性的程序设计。在一个程序中可以有多条断言，以便确保程序计算的正确性。<br />
PHP提供了assert函数，当执行到此函数时，如果条件为真，则什么都不执行，如果条件为假，则警告并中断程序： Warning: assert() [function.assert]: Assertion failed<br />
经常我们会用echo或die来调试我们的程序，在调试完后我们需要删除相关调试代码。使用assert语句可以在出现问题时将程序调用，而不需要在后面将这些断言删除，这样可以节省删除操作并且在以后的维护过程中也可以重用这些语句，这里就有点测试的感觉了。<br />
当然，我们也可以将断言和异常一起使用，如下所示代码：</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
</pre></td><td class="code"><pre class="php" style="font-family:monospace;">&nbsp;
<span style="color: #009933; font-style: italic;">/**
 * 断言回调函数，抛出异常
 */</span>
<span style="color: #000000; font-weight: bold;">function</span> assert_callcack<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #b1b100;">throw</span> <span style="color: #000000; font-weight: bold;">new</span> Exception<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;msg&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">// Set our assert options</span>
<span style="color: #990000;">assert_options</span><span style="color: #009900;">&#40;</span>ASSERT_ACTIVE<span style="color: #339933;">,</span>   <span style="color: #009900; font-weight: bold;">true</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #990000;">assert_options</span><span style="color: #009900;">&#40;</span>ASSERT_BAIL<span style="color: #339933;">,</span>     <span style="color: #009900; font-weight: bold;">true</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #990000;">assert_options</span><span style="color: #009900;">&#40;</span>ASSERT_WARNING<span style="color: #339933;">,</span>  <span style="color: #009900; font-weight: bold;">true</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #666666; font-style: italic;">// 必须为true</span>
<span style="color: #990000;">assert_options</span><span style="color: #009900;">&#40;</span>ASSERT_CALLBACK<span style="color: #339933;">,</span> <span style="color: #0000ff;">'assert_callcack'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">/* 触发一个断言*/</span>
<span style="color: #990000;">assert</span><span style="color: #009900;">&#40;</span><span style="color: #cc66cc;">0</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #b1b100;">echo</span> <span style="color: #0000ff;">'Never reached'</span><span style="color: #339933;">;</span></pre></td></tr></table></div>

<p>断言和异常的结合处在于断言的回调函数，只是需要注意的是：assert_options(ASSERT_WARNING,  true);<br />
因为断言的错误级别为warning。</p>
]]></content:encoded>
			<wfw:commentRss>https://www.phppan.com/2010/12/thinkinphp-3-exception/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>思考PHP语言二：面向对象</title>
		<link>https://www.phppan.com/2010/12/thinkinphp-2-oop/</link>
		<comments>https://www.phppan.com/2010/12/thinkinphp-2-oop/#comments</comments>
		<pubDate>Mon, 20 Dec 2010 01:00:32 +0000</pubDate>
		<dc:creator><![CDATA[admin]]></dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[思考PHP语言]]></category>
		<category><![CDATA[面向对象]]></category>

		<guid isPermaLink="false">http://www.phppan.com/?p=1190</guid>
		<description><![CDATA[思考PHP语言二：面向对象 【概述】 PHP是一门支持面向过程，也支持面向对象的动态语言。从PHP5开始，PH [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>思考PHP语言二：面向对象<br />
<strong>【概述】</strong><br />
PHP是一门支持面向过程，也支持面向对象的动态语言。从PHP5开始，PHP对于面向对象的支持好了很多。<br />
面向对象程序设计是抽象数据类型的抽象原理的一种应用。当我们使用类时，我们应该了解这是一种抽象数据类型，对象是属于所对应类的类型的。<br />
面向对象的三个特征：封装，继承，多态。这三个特征也可以用：抽象数据类型，继承和方法调用与方法间的动态绑定来说明。抽象是我们与程序复杂性抗争的一种方式，通过这种方式，我们可以关注并且仅关注主要的属性而忽略次要的属性。从语法的角度来说，抽象数据类型是一种封装，它不仅仅包括对于数据的封装，也包括其提供方法的封装。通过访问控制，从而实现数据或方法的隐藏和暴露，这就是我们经常所说的类，它的实例我们称之为对象。</p>
<p><strong>【PHP的抽象数据类型】</strong><br />
PHP以类的形式实现封装，类中所定义的数据称为成员变量；而类中所定义的函数称为成员函数或成员方法。成员函数和成员变量又分别有类属性和实例属性。<br />
<strong>类属性的成员函数和成员变量</strong><br />
PHP中的类属性成员都以静态的方式存在，为所有的实例共享（包括成员函数和成员变量），可以通过类名直接调用。但是其仅在一个PHP的生命周期内有效，这与java等有较大的差别。<br />
<strong>实例属性的成员函数和成员变量</strong><br />
对于实例属性的成员函数和成员变量，一个类的所有实例共享一套成员函数，而每个实例都有属于自己的一套成员变量，这也是我们在做面向对象的程序结构设计时将数据尽量向下移，将共用的方法尽量向上移的原因。<br />
<strong>信息隐藏</strong><br />
PHP中的信息隐藏通过访问控制实现，对于需要隐藏的数据将其以私有成员定义，在其声明前添加private关键字，对于需要公开的数据将其以公有成员定义，在其定义前添加public关键字，也可以不加任何关键字，因为PHP默认情况下是public。PHP的私有和公有访问权限与java相同，</p>
<p><strong>命名封装</strong><br />
在构建大型系统时，为解决不同团队对于函数或类等的命名冲突，我们需要引入命名封装，命名封装是一些逻辑上的封装。在PHP中使用命名空间实现，只是这在PHP５.3版本后才有相关支持。<br />
在PHP中，类，函数和常量这三种类型受命名空间的影响，命名空间通过关键字namespace 来声明，对于层次化的命名空间以反斜杠隔开，如：namespace com\toll\level;</p>
<p><strong>【PHP的继承】</strong><br />
继承是软件复用的一种形式，它不仅可以让程序人员以一个已有类为基础，设计一个修改了的后代类型，还可以定义相关的程序结构和关系。这种结构和关系在一定程度上反映了这些实体的上下代关系。从这里就产生了父类，子类等概念，并且在访问控制中也产生了protected，使用protected时，它的最大访问范围为其派生类。在子类中我们可以定义新的成员变量和新的成员函数，并且可以重载父类的成员函数，但是无法重载父类的构造函数，如果在实例化时需要调用父类的构造函数，我们需要手动调用父类的构造函数，PHP本身不会自动调用。<br />
另外，关于PHP的构造函数的一个历史遗留问题：以类名为构造函数和以__construct为构造函数，在之前写过一篇文章介绍二者在调用时的选择方式。<a href="http://www.phppan.com/2010/11/php-source-27-construct/">PHP源码阅读笔记二十七：PHP对构造方法的识别</a><br />
PHP没有多继承，只支持单继承，但是他拥有接口，它提供了一种多继承的方式。这点和java一样。<br />
接口的定义与类的定义类似，只是关键字变成了interface，接口可以包含常量和方法声明。它的作用仅仅是定义类的说明。类可以实现多个接口，但是类也必须实现接口中的所有方法。接口可以模拟实现多继承，也提供了另一种形式的多态，但是这对于PHP来说没有多大的意义，因为PHP的变量本身就是多态的。</p>
<p>继承是作为增加复用可能性的一种手段，但是它在继承层次中产生的类之间的相互依赖性，产生了一些强耦合。而这与之前的封装的优点刚好相反，封装就是为了保持类之间的相互独立性。所以在作设计时，我们如果使用继承就需要考虑是否真的需要，是否真的是is-a的关系。更多的时候我们会选择使用委托来实现。<br />
<strong>【PHP的动态绑定】</strong><br />
PHP本身就是动态绑定的。</p>
]]></content:encoded>
			<wfw:commentRss>https://www.phppan.com/2010/12/thinkinphp-2-oop/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>思考PHP语言一：控制结构</title>
		<link>https://www.phppan.com/2010/12/thinkinphp-1-control-structures/</link>
		<comments>https://www.phppan.com/2010/12/thinkinphp-1-control-structures/#comments</comments>
		<pubDate>Wed, 15 Dec 2010 03:10:02 +0000</pubDate>
		<dc:creator><![CDATA[admin]]></dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[思考PHP语言]]></category>

		<guid isPermaLink="false">http://www.phppan.com/?p=1181</guid>
		<description><![CDATA[思考PHP语言一：控制结构 【概述】 命令式程序设计语言的实质是赋值语句占主导地位。 赋值语句的目的是改变变量 [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>思考PHP语言一：控制结构<br />
<strong>【概述】</strong><br />
命令式程序设计语言的实质是赋值语句占主导地位。 赋值语句的目的是改变变量的值，因此在所有的命令式程序设计语言中，其共同部分就是不停的变幻变量的值，最后达到我们的目的。<br />
然而我们的程序并不是仅仅是由赋值语句组成的。至少还需要两种额外的语言机制：<br />
1、控制路径选择的方法。<br />
2、控制某些语句重复执行的方法。<br />
这些方法或语言机制我们称之为控制语句。<br />
大量的控制语句可以提高程序语言的可写性，但是同时又会降低程序语言的可读性，为此，经常需要在这二者之间进行权衡。<br />
</strong>【PHP中的选择语句】</strong><br />
<strong>1、双向选择语句</strong><br />
示例：</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
</pre></td><td class="code"><pre class="php" style="font-family:monospace;"><span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span>expr<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
	statement
<span style="color: #009900;">&#125;</span><span style="color: #b1b100;">else</span><span style="color: #009900;">&#123;</span>
	statement
<span style="color: #009900;">&#125;</span></pre></td></tr></table></div>

<p>PHP选择语句中的逻辑表达式可以是布尔表达式，也可以是结果为数字的表达式，但是在PHP内部只有一种变量zval，于是这些表达式结果类型对于PHP来说没有多大的意义</p>
<p>在PHP中，then子句和else子句可以是简单语句也可以是复合语句，如果是复合语句需要使用大括号将所有的复合语句括起来。</p>
<p>关于else的归属问题，以就近原则为准，如果需要在一个then子句中包含一个if语句，建议将其以复合语句处理，使用大括号将if语句括起来。如下所示代码：</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
</pre></td><td class="code"><pre class="php" style="font-family:monospace;"><span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span>expr<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
	<span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span>expr2<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
		statement
	<span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span><span style="color: #b1b100;">else</span><span style="color: #009900;">&#123;</span>
	statement
<span style="color: #009900;">&#125;</span></pre></td></tr></table></div>

<p><strong>2、多向选择语句</strong><br />
多向选择语句允许在任意数目的语句或语句组中进行一种选择。多向选择器与双向选择器可以互相构造，都可以实现对方的功能。<br />
示例：</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
</pre></td><td class="code"><pre class="php" style="font-family:monospace;"><span style="color: #b1b100;">switch</span><span style="color: #009900;">&#40;</span>expr<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
<span style="color: #b1b100;">case</span> 常量表达式<span style="color: #cc66cc;">1</span>：
	statement <span style="color: #cc66cc;">1</span><span style="color: #339933;">;</span>
	<span style="color: #b1b100;">break</span><span style="color: #339933;">;</span>
<span style="color: #339933;">......</span>
&nbsp;
<span style="color: #b1b100;">case</span> 常量表达式n：
	statement n<span style="color: #339933;">;</span>
	<span style="color: #b1b100;">break</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#91;</span><span style="color: #b1b100;">default</span><span style="color: #339933;">:</span> statement n <span style="color: #339933;">+</span> <span style="color: #cc66cc;">1</span><span style="color: #339933;">;</span><span style="color: #009900;">&#93;</span>
&nbsp;
<span style="color: #009900;">&#125;</span></pre></td></tr></table></div>

<p>PHP的switch语句使用了C的switch语句的语法，但是却有一些差别，PHP的case 表达式可以是数字，字符串或浮点数这些简单类型。<br />
与双向选择语句一样，多向选择语句在选择的路径上可以是简单语句，也可以是复合语句，只是这里我们不需要使用大括号，此时我们可以叫它语句序列。<br />
当所有的情况都不满足时，执行default路径，如果没有所谓的default情况，请将default子句也写上，并且报错吧。<br />
但是，当出现了switch选择语句时，此时可以想想我们的代码是否可以重构了。<br />
当某个case下没有 break语句时，请写下注释说明原因。</p>
<p></strong>【PHP中的循环语句】</strong><br />
循环语句的作用是将一条或一组语句执行n(n>=0)的一种语句<br />
在函数式程序设计语言中一般是通过递归完成循环语句的功能<br />
<strong>1、计数器循环控制语句</strong><br />
这种形式的循环控制语句一般包括初始值，终值，步长，这些统称为循环参数<br />
PHP的计数器循环控制语句是类似于C语言的。<br />
示例如下：</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
</pre></td><td class="code"><pre class="php" style="font-family:monospace;"><span style="color: #b1b100;">for</span> <span style="color: #009900;">&#40;</span>表达式<span style="color: #cc66cc;">1</span><span style="color: #339933;">;</span> 表达式<span style="color: #cc66cc;">2</span>；表达式<span style="color: #cc66cc;">3</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
	循环体
<span style="color: #009900;">&#125;</span></pre></td></tr></table></div>

<p>这就是我们所说的for语句，只是在PHP中，for语句的使用较少，用得最多的还是在后面会提到的基于数据结构的循环&#8212;foreach<br />
for语句中的三个表达式都是可选的，如果缺少第二个表达式，则认为其结果为真，如果在循环体中没有退出操作的话，这将是一个死循环。并且每个表达式都是可以由多条语句组成，语句与语句之间用逗号隔开，此时表达式的值为最后一条语句的值。<br />
虽然for语句属于计数器循环控制语句，但是它并没有明显的循环变量或循环参数，可以在循环体中改变所有的所有变量，这就导致了for语句的灵活性，同时，如果用得不好也将导致程序逻辑的混乱<br />
<strong>2、逻辑控制循环语句</strong><br />
逻辑控制循环语句是基于布尔表达式的，所有的计数循环都可以使用逻辑循环来实现，反过来则不一定。<br />
示例：</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
</pre></td><td class="code"><pre class="php" style="font-family:monospace;"><span style="color: #b1b100;">while</span> <span style="color: #009900;">&#40;</span>控制表达式<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    循环体
<span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #b1b100;">do</span> <span style="color: #009900;">&#123;</span>
   循环体
<span style="color: #009900;">&#125;</span><span style="color: #b1b100;">while</span><span style="color: #009900;">&#40;</span>控制表达式<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></td></tr></table></div>

<p>逻辑控制语句分为先测试和后测试两种情况，这个在上面的示例中有所体现。与for语句一样，PHP的逻辑循环控制语句也是类似于C语言的实现。<br />
对于while语句，当控制表达式的条件为真时执行循环体，对于do-while语句，先执行循环体，再判断控制表达式是否为真。while语句总会比do-while语句少执行一次。<br />
<strong>3、基于数据的循环语句</strong><br />
顾名思义，基于数据的循环语句的循环是由数据结构中的元素的数目来控制的。一般来说，基于数据的循环语句会使用一种称之为迭代器的函数来实现元素的遍历。<br />
PHP中可以使用预定义的一些函数来实现对数组的迭代访问，如current,next,reset等等。<br />
然而我们使用得最多的还是foreach语句，foreach可以直接迭代访问数组，如果用户自己定义的对象需要使用此语句进行迭代访问，必须实现SPL的迭代器。<br />
之前写过两篇关于迭代器的文章：<br />
<a href="http://www.phppan.com/2010/04/php-iterator-and-yii-cmapiterator/">PHP中迭代器的简单实现及Yii框架中的迭代器实现</a><br />
<a href="http://www.phppan.com/2010/04/php-source-24-iterator-false-value/">PHP源码阅读笔记二十四 ：iterator实现中当值为false时无法完成迭代的原因分析</a></p>
]]></content:encoded>
			<wfw:commentRss>https://www.phppan.com/2010/12/thinkinphp-1-control-structures/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>答10问PHP程序员</title>
		<link>https://www.phppan.com/2010/07/answer-10-question-of-php-coder/</link>
		<comments>https://www.phppan.com/2010/07/answer-10-question-of-php-coder/#comments</comments>
		<pubDate>Wed, 21 Jul 2010 05:59:22 +0000</pubDate>
		<dc:creator><![CDATA[admin]]></dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[程序相关]]></category>

		<guid isPermaLink="false">http://www.phppan.com/?p=834</guid>
		<description><![CDATA[在PPC看到这样一篇，觉得很有感触，很多东西都有些忘了，有些东西是不能放的，其地址为：http://bbs.p [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>在PPC看到这样一篇，觉得很有感触，很多东西都有些忘了，有些东西是不能放的，其地址为：http://bbs.phpchina.com/viewthread.php?tid=174331<br />
其内容及答案如下：</p>
<p>1.首先看了PHP的源码API函数，对于许多口水仗的争论一笑而过，只是停留在脚本级别上的什么效率，安全。。。之争完全就是无稽之谈，没有深入理解API，所有的争论都是臆测和不科学的态度。你做了吗？<br />
<strong>答：半年前就在看了，关注鸟哥blog。但最近兴趣和工作内容有所变化，</strong></p>
<p><strong><br />
</strong></p>
<p>2.不再把PHP看作一门后台语言，而是一门类似JS的脚本，页面表现级的语言，更多的是尝试使用一种软件来做后台，PHP做前台，尝试真正的B/S开发。你的看法呢？<br />
<strong>答：需要多学几种语言，每种语言都有其适用的领域，</strong></p>
<p><strong><br />
</strong></p>
<p>3.知识更新。PHP中的接口你懂了吗？反射你听过吗？JS中的事件冒泡你懂了吗？原型链知道吗？一切函数都是对象，你能理解否？MYSQL里面的视图，存储过程你尝试过么有？<br />
<strong>答：对于JS了解不多，PHP的接口，反射，mysql的视图，存储过程都有用过</strong></p>
<p><strong><br />
</strong></p>
<p>4.扎实的学知识。你是不是离开了JQ框架就连个DOM操作的原生JS都不会写了？你是不是离开了DB类，就连个简单的查询都不会写了？你是不是离开了IDE，连个表格都画不出来？你是不是到现在多表查询，子查询都还不会？你是不是到现在就只知道索引是用来加快查询的？<br />
你是不是到现在连个PHP5的稍微复杂点的OO类都还不会写？你会正则吗？你的E文水平咋样？<br />
<strong>答：如上题，js写得不多，由于是java出身，所有对面向对象的一些东西有一些了解，正则有一些了解，但还达不到《精通正则表达式》书中的内容，其它的都可以，可以直接看英文文档，虽然有一些慢</strong></p>
<p><strong><br />
</strong></p>
<p>5.扎实的算法基础。你知道选择排序，插入排序，冒泡排序，二分排序，希尔排序并且能写出来吗？你知道怎么遍历二叉树吗？知道霍夫曼吗？你知道图吗？你知道龙格-库塔，迭代，插值，雅戈尔，牛顿下山法吗？知道ZIP压缩原理吗？你是不是可爱到以为加减乘除加上循环判断就搞定了算法？你知道概率论，微积分，线性方程组在算法中是非常非常基础的吗？<br />
<strong>答：曾经的曾经，我以为我对算法和数据结构很了解，只是过了这几年发现自己忘记了，需要把它们捡起来</strong></p>
<p><strong><br />
</strong></p>
<p>6.学习的主动性。你是不是自己的网站连个拿的出手的JS都没有写过？你网站的效果是不是都是你下载的JQ插件弄出来的？到现在都还没有看过JQ的代码？你现在的模板引擎是谁的？DB类是谁的？框架是谁的？你是不是一直都很鄙视重复造轮子的事情，就像中国现在，“拿来主义”，永远是MADE IN CHINA,而不是Created in China？<br />
<strong>答：暂时没有自己写框架的打算，不过在项目中需要做一些文件架构的东东</strong></p>
<p><strong><br />
</strong></p>
<p>7.广泛的基础。你会汇编吗？那C总该会点吧。。那C++呢，那简单的JAVA总该会吧。。。那。。那傻瓜化的VB,NET,PY。。。？什么，你只会PHP？其他啥都不会？JS总该会吧？啊，不会，只会用网上下来的JQ？你除了PHP还会点啥？那假如PHP垮台了或者你所在的公司不用PHP了你吃什么？如果老板让你学J2SE你怕不怕？<br />
<strong>答：其实会很多种语言，只是都是会一点</strong></p>
<p><strong><br />
</strong></p>
<p>8.你是不是就准备一辈子做个coder?你的知识如果让你传授给别人的话，能支撑三个月吗？三个月后你还能讲得出点其他的东西吗？<br />
<strong>答：每天都在补充自己的知识，架子上的书也快放不下了，有些书需要再看一遍了</strong></p>
<p><strong><br />
</strong></p>
<p>9.你现在的水平和你刚开始学的时候进步了多少？你有过自己的作品吗？有多少代码是你自己写的？你认为是不是只要会写PHP代码就够了？这样的话一个初中生三个月后也就能达到你的水平了，你认为呢？你准备一直停留在这个水平吗？<strong><br />
答：现在不想看以前的代码了，觉得。。。。可能会往项目管理方面转</strong></p>
<p><strong><br />
</strong></p>
<p>10.最后一问，你除了会写仅会的PHP代码，还会点其他的吗？你有把握做其他工作吗？你能养活自己老婆孩子吗？能给他们幸福吗？<br />
<strong>答：我在努力 </strong></p>
<p><strong> </strong><br />
<strong>建议其它的phper也可以问下自己</strong></p>
]]></content:encoded>
			<wfw:commentRss>https://www.phppan.com/2010/07/answer-10-question-of-php-coder/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
