<?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; Yii框架</title>
	<atom:link href="https://www.phppan.com/tag/yii%e6%a1%86%e6%9e%b6/feed/" rel="self" type="application/rss+xml" />
	<link>https://www.phppan.com</link>
	<description>SaaS SaaS架构 团队管理 技术管理 技术架构 PHP 内核 扩展 项目管理</description>
	<lastBuildDate>Sat, 25 Apr 2026 00:56:17 +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>使用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>Yii 框架的视图层实现</title>
		<link>https://www.phppan.com/2013/02/yiiframework-view/</link>
		<comments>https://www.phppan.com/2013/02/yiiframework-view/#comments</comments>
		<pubDate>Sun, 17 Feb 2013 14:37:29 +0000</pubDate>
		<dc:creator><![CDATA[admin]]></dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[MVC]]></category>
		<category><![CDATA[Yii框架]]></category>
		<category><![CDATA[企业应用架构]]></category>

		<guid isPermaLink="false">http://www.phppan.com/?p=1793</guid>
		<description><![CDATA[如果你想看看 Yii 框架的视图实现过程，请继续向下；如果你想看看胖子的碎碎念，请直接拉到文章最后；如果你只是 [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>如果你想看看 Yii 框架的视图实现过程，请继续向下；如果你想看看胖子的碎碎念，请直接拉到文章最后；如果你只是路过，那也路过留名吧^_^。</p>
<p>Martin Flower 在《企业应用架构模式》中提到 MVC  模式的关键点在于两个分离：从模型中分离视图和从视图中分离控制器。视图的表现在很大程度上决定了此模式的使用，以及框架对 MVC 模式的各个层级的分离水平。 Yii  框架是一个基于 MVC 模式的框架，它在视图这块做了很多的工作，很清晰的实现了视图的功能。</p>
<p>Yii 框架的视图是一个包含了主要的用户交互元素的 PHP 脚本。每个视图有一个名字，当渲染( render  )时，名字会被用于识别视图脚本文件。视图的名称与其视图脚本名称是一样的。例如:视图 edit 的名称出自一个名为 edit.php  的脚本文件。要渲染时，需通过传递视图的名称调用 CController::render()。这个方法将在 “protected/views/控制器 ID”  目录下寻找对应的视图文件，其寻找方法为 getViewFile。这里的 protected/views 只是默认的存储位置，我们可以通过  Yii::app()-&gt;setViewPath 方法改变此路径。</p>
<p>在视图脚本内部,我们可以通过 $this  来访问控制器实例。同时，我们也可以在视图里以“$this-&gt;属性名”的方式获取控制器的任何属性，这种调用方式是通过实现__get魔法方法实现的。</p>
<p>一次较为完整的视图渲染过程在 CController 类的 render 函数中体现得淋漓尽致。当控制器中从模型（model）中拿到数据后，一般会执行  render() 方法创建视图，其大概过程如下：</p>
<ol>
<li>执行预留的 beforeRender 钩子。</li>
<li>查找渲染局部内容 $output，实际上这里是一个部分视图渲染的过程，它包括获取视图文件路径，渲染视图文件，处理输出三个部分。在渲染的过程中，通过  PHP 中的 extract() 方法把数组中将变量导入到当前的符号表，直接 require 视图文件，从而合并数据和表现。</li>
<li>如果存在布局，则将得到的内容放入以 content 为下标的的数组传递给父类的 renderFile() 方法中，重复执行渲染视图的过程。在布局中执行  <strong><!--?php echo $content; ?--></strong>，输出局部内容$output，实现了局部和布局视图的合并。为了实现多级布局，在布局中还可以通过控制器的视图装饰方法加载。</li>
<li>执行预留的 afterRender 钩子。</li>
</ol>
<p>在渲染视图的时候，如果参数中有传递对应的值，会执行 processOutput() 方法，此方法一般在渲染视图结束时才会调用，它实现了三个过程：</p>
<ol>
<li>注册客户端脚本，具体由 ClientScript 组件管理。</li>
<li>如果存在，则执行动态内容输出。</li>
<li>页面内容 base64_encode 加密，如果存在 zlib 扩展，则会先压缩。</li>
</ol>
<p>在 CController 类中对视图的渲染除了上面的render方法外，还有其它多种方法：</p>
<ul>
<li>render方法： 和布局一起渲染 render($view,$data=null,$return=false)</li>
<li>renderPartial方法： 仅渲染视图内容，或者是渲染部分页面内容。它与 render() 方法的不同是它不会渲染布局，并且在 render()  方法中也会调用此方法。 renderPartial($view,$data=null,$return=false,$processOutput=false)</li>
<li>renderText方法：渲染静态内容和布局。renderText($text,$return=false)</li>
<li>renderDynamic方法：通过回调函数渲染动态内容，通常我们会在模板文件中中调用此方法。renderDynamic($callback)-&gt;renderDynamicInternal($callback,$params)</li>
<li>renderClip方法：渲染显示 CClipWidget  生成的内容，此处需要指定名字。renderClip($name,$params=array(),$return=false)</li>
</ul>
<p>对于不同的页面中共用的内容，虽然可以通过 renderPartial  方法渲染部分页面视图，但是必然存在对于数据部分的重复，因为这些视图都需要调用控制提供的数据，从而产生耦合。因此 Yii 框架  提供了另一个独立的视图部件，官方称之为 Widget （小物件？小挂件？）。</p>
<p>小物件是 CWidget  或其子类的实例。它是一个主要用于表现数据的组件。小物件通常内嵌于一个视图来产生一些复杂而独立的用户界面。也算是一种界面的独立和松耦合的设计。如我们做WEB应用时常用的列表，翻页，日历等。这些  Widget 增加了界面的复用度，减少了代码量。</p>
<p>与前面视图部分不同的是，它没有布局文件支持，并且 Widget 视图中的 $this 指向 Widget  实例而不是控制器实例，这里实现了与控制器的分离。如果要实现一个自定义的 Widget ，我们仅需要继承 CWidget 并覆盖其 init() 和 run()  方法,可以定义一个新的 Widget 。</p>
<p>我们在视图中通过 $this-&gt;widget（） 或 $this-&gt;beginWidget() 和 $this-&gt;endWidget()  调用 Widget，两者的区别在于第二个方法可以在显示的过程中添加 html 内容。添加内容的位置在 init() 方法和 run()  方法输出的内容之间。</p>
<p>除了布局、Widget 外， Yii 框架实现系统级的视图，用来显示 Yii 的错误和日志信息。</p>
<p>系统视图的命名遵从了一些规则。比如像“errorXXX”这样的名称就是用于渲染展示错误号 XXX 的 CHttpException 的视图。在  framework/views 下, Yii 提供了一系列默认的系统视图. 我们可以通过在 protected/views/system  下创建同名视图文件进行自定义。系统默认的 exception 视图非常赞，结合 Yii 本身的 traces  机制，当抛出异常或出错时就会很详细的定位出问题的代码所在。</p>
<p>以上只是胖子阅读 Yii  框架源码的笔记。结合《企业应用架构模式》这本书的内容，如页面控制器、前端控制器、活动记录等，胖子发现对框架的实现有更深入的理解。一方面印证了书上的理论，一方面为实现过程的原理找到了出处。不晓得  Yii 框架的作者是否对此书也有精读，或者是经验的积累？</p>
<p>参考资料： http://www.yiiframework.com/doc/guide/1.1/en/basics.view</p>
]]></content:encoded>
			<wfw:commentRss>https://www.phppan.com/2013/02/yiiframework-view/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Yii框架的组件行为管理机制和Mix-in</title>
		<link>https://www.phppan.com/2011/11/yii-framework-component-behavior-and-mix-in/</link>
		<comments>https://www.phppan.com/2011/11/yii-framework-component-behavior-and-mix-in/#comments</comments>
		<pubDate>Mon, 07 Nov 2011 00:50:55 +0000</pubDate>
		<dc:creator><![CDATA[admin]]></dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[程序相关]]></category>
		<category><![CDATA[Mix-in]]></category>
		<category><![CDATA[Mixin]]></category>
		<category><![CDATA[php5.4]]></category>
		<category><![CDATA[Ruby]]></category>
		<category><![CDATA[Yii框架]]></category>

		<guid isPermaLink="false">http://www.phppan.com/?p=1500</guid>
		<description><![CDATA[Yii框架的组件行为管理机制和Mix-in 本文包括以下内容： Yii框架的组件行为管理机制介绍 Ruby、P [&#8230;]]]></description>
				<content:encoded><![CDATA[<p style="text-indent: 2em;">Yii框架的组件行为管理机制和Mix-in</p>
<p style="text-indent: 2em;">本文包括以下内容：</p>
<ul>
<li>Yii框架的组件行为管理机制介绍</li>
<li>Ruby、PHP5.4和Mix-in</li>
</ul>
<p style="text-indent: 2em;">在Yii框架的官网，我们可以看到关于<a style="color: #1299da; text-decoration: underline;" href="http://www.yiiframework.com/wiki/44/behaviors-events">Behaviors &amp; events</a>的介绍: Behaviors are simply a way of adding methods to an object.</p>
<p style="text-indent: 2em;">我们看官网上的使用示例：</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: #cc7833;">class</span> SomeClass <span style="color: #cc7833;">extends</span> CBehavior<span style="color: #ffffff;">{</span>
    <span style="color: #cc7833;">public</span> <span style="color: #cc7833;">function</span> add<span style="color: #ffffff;">(</span><span style="color: #6d9cbe;">$x</span><span style="color: #e0882f;">,</span> <span style="color: #6d9cbe;">$y</span><span style="color: #ffffff;">)</span> <span style="color: #ffffff;">{</span> <span style="color: #ff8400;">return</span> <span style="color: #6d9cbe;">$x</span> <span style="color: #e0882f;">+</span> <span style="color: #6d9cbe;">$y</span><span style="color: #e0882f;">;</span> <span style="color: #ffffff;">}</span>
<span style="color: #ffffff;">}</span>

<span style="color: #cc7833;">class</span> TestComponent <span style="color: #cc7833;">extends</span> CComponent <span style="color: #ffffff;">{</span>
<span style="color: #ffffff;">}</span>

<span style="color: #6d9cbe;">$test_comp</span> <span style="color: #e0882f;">=</span> <span style="color: #cc7833;">new</span> TestComponent<span style="color: #ffffff;">(</span><span style="color: #ffffff;">)</span><span style="color: #e0882f;">;</span>
<span style="color: #6d9cbe;">$test_comp</span><span style="color: #e0882f;">-&gt;</span><span style="color: #ffffff;">attachbehavior</span><span style="color: #ffffff;">(</span><span style="color: #56db3a;">'blah'</span><span style="color: #e0882f;">,</span> <span style="color: #cc7833;">new</span> SomeClass<span style="color: #ffffff;">)</span><span style="color: #e0882f;">;</span>
<span style="color: #6d9cbe;">$test_comp</span><span style="color: #e0882f;">-&gt;</span><span style="color: #ffffff;">add</span><span style="color: #ffffff;">(</span><span style="color: #1299da;">2</span><span style="color: #e0882f;">,</span> <span style="color: #1299da;">5</span><span style="color: #ffffff;">)</span><span style="color: #e0882f;">;</span></pre>
<p style="text-indent: 2em;">在TestComponent类的对象创建的后，我们可以通过调用attachbehavior给对象添加新的方法。</p>
<p style="text-indent: 2em;">通过其源码（在base/CComponent.php）可以知道它是通过在组件类内部以私有变量的方式存储这些添加的方法所在的对象， 通过魔术方法__call，当调用一个未定义的方法时需要调用__call方法的特性，遍历所有通过attachbehavior方法添加进来的对象， 并判断此对象是否禁用并且此对象是否存在需要调用的方法，如果存在则调用。</p>
<p style="text-indent: 2em;">此种实现方式存在如下一些问题：</p>
<ul>
<li>如果多个对象存在相同的方法，则程序调用时永远会调用第一次添加进去的方法</li>
<li>如果我们只是需要某个对象中的某个方法，但是在存储上需要将整个对象添加到列表中</li>
</ul>
<p style="text-indent: 2em;">也许你会觉得这些都是一些如果，都是一些假设，可能不会出现，这有些像众所周知的goto语句问题，如果用得好，这是一个利器，如果用得不好，可能会给你带来痛苦。 Yii框架中的这种机制实现运行时的方法绑定，虽然类的属性和实例参数仍然归属于其它类和对象。</p>
<p style="text-indent: 2em;">在官方说明中也提到了这是一种类似于ruby语言的实现方式，如果我们用Ruby实现上面的方法该如何写呢？如下：</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: #ff8400;">module</span> SomeClass
    <span style="color: #ff8400;">def</span> add<span style="color: #ffffff;">(</span>x, y<span style="color: #ffffff;">)</span>
        <span style="color: #cc7833;">return</span> x <span style="color: #e0882f;">+</span> y
    <span style="color: #ff8400;">end</span>
<span style="color: #ff8400;">end</span>

<span style="color: #ff8400;">class</span> TestComponet
    <span style="color: #ff8400;">include</span> SomeClass
<span style="color: #ff8400;">end</span>

test = TestComponet.<span style="color: #ffffff;">new</span>
<span style="color: #e2392d;">puts</span> test.<span style="color: #ffffff;">add</span><span style="color: #ffffff;">(</span><span style="color: #1299da;">10</span>, <span style="color: #1299da;">20</span><span style="color: #ffffff;">)</span></pre>
<p style="text-indent: 2em;">非常简单的实现了类的重用，我们知道在PHP中，接口是可以多继承的，但是接口只是形态上的多继承，是一种对于类实现的约束，是一种规格。 如果要实现这种类的重用，Ruby受Lisp的影响引入了Mix-in，在PHP5.4引入了trait关键字。</p>
<p style="text-indent: 2em;">在Ruby中Mix-in的关键字是module，而在即将推出的PHP5.4，其对应的关键字是trait； 如果要复用这个定义的类，在Ruby中使用include，而在PHP5.4中使用use。如下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: #cc7833;">&lt;?PHP</span>
trait SomeClass <span style="color: #ffffff;">{</span>
    <span style="color: #cc7833;">public</span> <span style="color: #cc7833;">function</span> add<span style="color: #ffffff;">(</span><span style="color: #6d9cbe;">$x</span><span style="color: #e0882f;">,</span> <span style="color: #6d9cbe;">$y</span><span style="color: #ffffff;">)</span> <span style="color: #ffffff;">{</span>
        <span style="color: #ff8400;">return</span> <span style="color: #6d9cbe;">$x</span> <span style="color: #e0882f;">+</span> <span style="color: #6d9cbe;">$y</span><span style="color: #e0882f;">;</span>
    <span style="color: #ffffff;">}</span>
<span style="color: #ffffff;">}</span>

<span style="color: #cc7833;">class</span> TestComponent <span style="color: #ffffff;">{</span>
    use SomeClass<span style="color: #e0882f;">;</span>
<span style="color: #ffffff;">}</span>

<span style="color: #6d9cbe;">$obj</span> <span style="color: #e0882f;">=</span> <span style="color: #cc7833;">new</span> TestComponent<span style="color: #ffffff;">(</span><span style="color: #ffffff;">)</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;">$obj</span><span style="color: #e0882f;">-&gt;</span><span style="color: #ffffff;">add</span><span style="color: #ffffff;">(</span><span style="color: #1299da;">10</span><span style="color: #e0882f;">,</span> <span style="color: #1299da;">20</span><span style="color: #ffffff;">)</span><span style="color: #e0882f;">;</span></pre>
<p style="text-indent: 2em;">对于Mix-in类，有两个约束：</p>
<ul>
<li>不能单独生成实例</li>
<li>不能继承其它的普通类</li>
</ul>
<p style="text-indent: 2em;">如果实例这个类程序执行会显示：</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;">Fatal error: Cannot instantiate trait SomeClass...</pre>
<p style="text-indent: 2em;">如果从其它普通类继承会显示：</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;">Fatal error: A trait (SomeClass) cannot extend a class ...</pre>
<p style="text-indent: 2em;">如果要查找这两个约束的源码实现，可以直接在源码中搜索Cannot instantiate trait和cannot extend a class。 从搜索可以看出：</p>
<ul>
<li>不能单独生成实例的检测是在new关键字的中间代码执行时执行的，在Zend/zend_vm_execture.h文件</li>
<li>不能继承的约束是在编译成中间代码的过程中实现的，在 Zend/zend_compile.c文件</li>
</ul>
<p style="text-indent: 2em;">在面向对象编程语言，Mix-in是一个提供了一些被用于继承或在子类中重用的功能的类，它类似于一种多继承， 但是实际上它是一种中小粒度的代码复用单元，而不直接用于实例化。 虽然这不是一种专业的方式进行功能复用，这在实现多继承的同时，在一定程序上避免了多继承的明显问题。 一如Yii的组件行为管理机制，也是另外一种取巧的Mix-in实现。</p>
]]></content:encoded>
			<wfw:commentRss>https://www.phppan.com/2011/11/yii-framework-component-behavior-and-mix-in/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Yii框架中有点意思的文件缓存</title>
		<link>https://www.phppan.com/2011/01/yii-filecache/</link>
		<comments>https://www.phppan.com/2011/01/yii-filecache/#comments</comments>
		<pubDate>Fri, 21 Jan 2011 10:01:53 +0000</pubDate>
		<dc:creator><![CDATA[admin]]></dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Yii框架]]></category>
		<category><![CDATA[缓存]]></category>

		<guid isPermaLink="false">http://www.phppan.com/?p=1228</guid>
		<description><![CDATA[Yii框架中有点意思的文件缓存 在Yii框架的framework/caching目录下是Yii框架的所有缓存操 [&#8230;]]]></description>
				<content:encoded><![CDATA[<h1 style="font-weight: normal; font-family: 'Microsoft YaHei', Helvetica, Arial, sans-serif; font-size: 1.4em; color: #006ea3; margin-top: 10px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; padding-bottom: 10px; border-bottom-width: 1px; border-bottom-style: solid; border-bottom-color: #aaaaaa;">Yii框架中有点意思的文件缓存</h1>
<p style="text-indent: 2em;">在Yii框架的framework/caching目录下是Yii框架的所有缓存操作。包括文件缓存，APC缓存、Db缓存，Memcache缓存等。 今天我们要说的是文件缓存。</p>
<h2 style="font-weight: bold; font-family: 'Microsoft YaHei', Helvetica, Arial, sans-serif; font-size: 1.2em; color: #333333;">【文件和类结构】</h2>
<p style="text-indent: 2em;">它总共包括CFileCache.php、CCache.php和接口文件。 缓存基类CCache抽象类实现了CApplicationComponent类，ICache, ArrayAccess接口。 实现类CFileCache继承自CCache基类。其它如Memcache等缓存也是继承这个基类。 在ICache接口中统一缓存接口，在CCache基类中统一对外的接口，以类似于模板方法模式的方式将对于增加，修改，删除操作延迟到子类实现。</p>
<h2 style="font-weight: bold; font-family: 'Microsoft YaHei', Helvetica, Arial, sans-serif; font-size: 1.2em; color: #333333;">【缓存方案】</h2>
<p style="text-indent: 2em;">指定缓存目录，以一条数据一个文件的方式存储。序列化使用PHP自带的serialize函数。 如果缓存数据过多，作者建议使用多级目录，多级目录会自动生成，默认为0，即当前目录，推荐使用3级以下的子目录。 对于缓存过期是以文件的修改时间为准（filemtime函数）。在获取数据时，如果文件过期，则取的数据为空。</p>
<h2 style="font-weight: bold; font-family: 'Microsoft YaHei', Helvetica, Arial, sans-serif; font-size: 1.2em; color: #333333;">【有点意思的地方】</h2>
<p style="text-indent: 2em;">个人觉得有点意思的地方在于其对于过期缓存的批量处理，在程序中作者称其为garbage collection。 看其实现代码：</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: #ff8400;">if</span><span style="color: #ffffff;">(</span><span style="color: #e0882f;">!</span><span style="color: #6d9cbe;">$this</span><span style="color: #e0882f;">-&gt;</span>_gced <span style="color: #e0882f;">&amp;&amp;</span> <a style="color: #1299da; text-decoration: none;" href="http://www.php.net/mt_rand"><span style="color: #e2392d;">mt_rand</span></a><span style="color: #ffffff;">(</span><span style="color: #1299da;">0</span><span style="color: #e0882f;">,</span><span style="color: #1299da;">1000000</span><span style="color: #ffffff;">)</span><span style="color: #e0882f;">&lt;</span><span style="color: #6d9cbe;">$this</span><span style="color: #e0882f;">-&gt;</span>_gcProbability<span style="color: #ffffff;">)</span>
<span style="color: #ffffff;">{</span>
    <span style="color: #6d9cbe;">$this</span><span style="color: #e0882f;">-&gt;</span><span style="color: #ffffff;">gc</span><span style="color: #ffffff;">(</span><span style="color: #ffffff;">)</span><span style="color: #e0882f;">;</span>    <span style="color: #bc9458; font-style: italic;">//  清除过期的缓存文件</span>
    <span style="color: #6d9cbe;">$this</span><span style="color: #e0882f;">-&gt;</span>_gced<span style="color: #e0882f;">=</span><span style="color: #cc7833;">true</span><span style="color: #e0882f;">;</span>
<span style="color: #ffffff;">}</span></pre>
<p style="text-indent: 2em;">各位看官，你应该知道这段代码是啥意思了。 有点意思的地方是和PHP源码中对于session过期的处理。如下所示源码：</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: #ff8400;">if</span> <span style="color: #ffffff;">(</span>PS<span style="color: #ffffff;">(</span>mod_data<span style="color: #ffffff;">)</span> <span style="color: #e0882f;">&amp;&amp;</span> PS<span style="color: #ffffff;">(</span>gc_probability<span style="color: #ffffff;">)</span> <span style="color: #e0882f;">&gt;</span> <span style="color: #1299da;">0</span><span style="color: #ffffff;">)</span> <span style="color: #ffffff;">{</span>
    <span style="color: #1299da;">int</span> nrdels <span style="color: #e0882f;">=</span> <span style="color: #e0882f;">-</span><span style="color: #1299da;">1</span><span style="color: #e0882f;">;</span>

    nrand <span style="color: #e0882f;">=</span> <span style="color: #ffffff;">(</span><span style="color: #1299da;">int</span><span style="color: #ffffff;">)</span> <span style="color: #ffffff;">(</span><span style="color: #ffffff;">(</span><span style="color: #1299da;">float</span><span style="color: #ffffff;">)</span> PS<span style="color: #ffffff;">(</span>gc_divisor<span style="color: #ffffff;">)</span> <span style="color: #e0882f;">*</span> php_combined_lcg<span style="color: #ffffff;">(</span>TSRMLS_C<span style="color: #ffffff;">)</span><span style="color: #ffffff;">)</span><span style="color: #e0882f;">;</span>
    <span style="color: #ff8400;">if</span> <span style="color: #ffffff;">(</span>nrand <span style="color: #e0882f;">&lt;</span> PS<span style="color: #ffffff;">(</span>gc_probability<span style="color: #ffffff;">)</span><span style="color: #ffffff;">)</span> <span style="color: #ffffff;">{</span>
        <span style="color: #bc9458; font-style: italic;">//  调用定义的垃圾收集方法</span>
        PS<span style="color: #ffffff;">(</span>mod<span style="color: #ffffff;">)</span><span style="color: #e0882f;">-&gt;</span>s_gc<span style="color: #ffffff;">(</span><span style="color: #e0882f;">&amp;</span>PS<span style="color: #ffffff;">(</span>mod_data<span style="color: #ffffff;">)</span><span style="color: #e0882f;">,</span> PS<span style="color: #ffffff;">(</span>gc_maxlifetime<span style="color: #ffffff;">)</span><span style="color: #e0882f;">,</span> <span style="color: #e0882f;">&amp;</span>nrdels TSRMLS_CC<span style="color: #ffffff;">)</span><span style="color: #e0882f;">;</span>
        ...
    <span style="color: #ffffff;">}</span>
<span style="color: #ffffff;">}</span></pre>
<p style="text-indent: 2em;">对比下变量名，对比下调用方式。 ^_^</p>
]]></content:encoded>
			<wfw:commentRss>https://www.phppan.com/2011/01/yii-filecache/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>YII框架中可以使用foreach遍历对象以及可以使用数组形式直接访问对象的原因</title>
		<link>https://www.phppan.com/2010/05/yii-foreach-arrayaccess/</link>
		<comments>https://www.phppan.com/2010/05/yii-foreach-arrayaccess/#comments</comments>
		<pubDate>Tue, 04 May 2010 01:05:27 +0000</pubDate>
		<dc:creator><![CDATA[admin]]></dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[ArrayAccess]]></category>
		<category><![CDATA[Iterator]]></category>
		<category><![CDATA[IteratorAggregate]]></category>
		<category><![CDATA[Yii框架]]></category>

		<guid isPermaLink="false">http://www.phppan.com/?p=672</guid>
		<description><![CDATA[YII框架中可以使用foreach遍历对象以及可以使用数组形式直接访问对象的原因 在YII框架的使用过程中，我 [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>YII框架中可以使用foreach遍历对象以及可以使用数组形式直接访问对象的原因<br />
在YII框架的使用过程中，我们可以使用foreach直接遍历findAll等方法返回的对象的属性<br />
为什么呢？其实这与CModel实现的接口相关，接下来我们看下其实现的整个过程<br />
对于一个我们定义的model，它会继承虚类CActiveRecord，CActiveRecord类继承于CModel，如下所示：</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;">class</span> special <span style="color: #000000; font-weight: bold;">extends</span> CActiveRecord <span style="color: #009900;">&#123;</span>
<span style="color: #009900;">&#125;</span>
<span style="color: #000000; font-weight: bold;">abstract</span> <span style="color: #000000; font-weight: bold;">class</span> CActiveRecord <span style="color: #000000; font-weight: bold;">extends</span> CModel<span style="color: #009900;">&#123;</span>
<span style="color: #009900;">&#125;</span></pre></td></tr></table></div>

<p>
最关键的地方是CModel类实现了IteratorAggregate接口。<br />
而在CModel类中实现的getIterator方法返回的是这个model的所有属性，使用的迭代器是Yii框架实现的CMapIterator，而CMapIterator实现了Iterator接口</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
</pre></td><td class="code"><pre class="php" style="font-family:monospace;"><span style="color: #009933; font-style: italic;">/**
* Returns an iterator for traversing the attributes in the model.
* This method is required by the interface IteratorAggregate.
* @return CMapIterator an iterator for traversing the items in the list.
*/</span>
<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> getIterator<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
<span style="color: #000088;">$attributes</span><span style="color: #339933;">=</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getAttributes</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #b1b100;">return</span> <span style="color: #000000; font-weight: bold;">new</span> CMapIterator<span style="color: #009900;">&#40;</span><span style="color: #000088;">$attributes</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></td></tr></table></div>

<p>这些就使得我们可以使用foreach直接遍历findAll等方法返回的对象<br />
关于此迭代器可以参看之前写的关于迭代器的文章：<br />
<a href="http://www.phppan.com/2010/04/php-source-24-iterator-false-value/">PHP源码阅读笔记二十四 ：iterator实现中当值为flase时无法完成迭代的原因分析</a></p>
<p>关于IteratorAggregate接口请移步<br />
<a href="http://cn.php.net/manual/en/class.iteratoraggregate.php">http://cn.php.net/manual/en/class.iteratoraggregate.php</a><br />
关于Iterator接口请移步<br />
<a href="http://cn.php.net/manual/en/class.iterator.php">http://cn.php.net/manual/en/class.iterator.php</a></p>
<p>
同样的道理，<br />
因为CModel实现了ArrayAccess接口，所以可以直接访问以数组的方式访问<br />
关于ArrayAccess接口请移步<br />
<a href="http://cn.php.net/manual/en/class.arrayaccess.php">http://cn.php.net/manual/en/class.arrayaccess.php</a></p>
]]></content:encoded>
			<wfw:commentRss>https://www.phppan.com/2010/05/yii-foreach-arrayaccess/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>PHP中迭代器的简单实现及Yii框架中的迭代器实现</title>
		<link>https://www.phppan.com/2010/04/php-iterator-and-yii-cmapiterator/</link>
		<comments>https://www.phppan.com/2010/04/php-iterator-and-yii-cmapiterator/#comments</comments>
		<pubDate>Sat, 24 Apr 2010 00:54:14 +0000</pubDate>
		<dc:creator><![CDATA[admin]]></dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Iterator]]></category>
		<category><![CDATA[PHP应用]]></category>
		<category><![CDATA[Yii框架]]></category>
		<category><![CDATA[设计模式]]></category>
		<category><![CDATA[迭代器]]></category>

		<guid isPermaLink="false">http://www.phppan.com/?p=652</guid>
		<description><![CDATA[PHP中迭代器的简单实现及Yii框架中的迭代器实现 在维基百科中我们可以看到其定义如下： 迭代器有时又称光标（ [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>PHP中迭代器的简单实现及Yii框架中的迭代器实现<br />
在维基百科中我们可以看到其定义如下：<br />
迭代器有时又称光标（cursor）是程式设计的软件设计模式，可在容器物件（container，例如list或vector）上遍访的接口，设计人员无需关心容器物件的内容。<br />
各种语言实作Iterator的方式皆不尽同，有些面向对象语言像Java, C#, Python, Delphi都已将Iterator的特性内建语言当中，完美的跟语言整合，我们称之隐式迭代器（implicit iterator），但像是C++语言本身就没有Iterator的特色，但STL仍利用template实作了功能强大的iterator。<br />
Iterator另一方面还可以整合Generator。有些语言将二者视为同一接口，有些语言则将之独立化。<br />
地址：http://zh.wikipedia.org/zh-cn/%E8%BF%AD%E4%BB%A3%E5%99%A8<br />
【Iterator的简单实现】</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
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
</pre></td><td class="code"><pre class="php" style="font-family:monospace;"><span style="color: #009933; font-style: italic;">/**
* Iterator模式的简单实现类
*/</span>
<span style="color: #000000; font-weight: bold;">class</span> sample implements Iterator <span style="color: #009900;">&#123;</span>
    <span style="color: #000000; font-weight: bold;">private</span> <span style="color: #000088;">$_items</span> <span style="color: #339933;">;</span>
&nbsp;
    <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: #339933;">&amp;</span><span style="color: #000088;">$data</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_items <span style="color: #339933;">=</span> <span style="color: #000088;">$data</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> <span style="color: #990000;">current</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #b1b100;">return</span> <span style="color: #990000;">current</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_items<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> <span style="color: #990000;">next</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #990000;">next</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_items<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>   
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> <span style="color: #990000;">key</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #b1b100;">return</span> <span style="color: #990000;">key</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_items<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> <span style="color: #990000;">rewind</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #990000;">reset</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_items<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> valid<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>                                                                              
        <span style="color: #b1b100;">return</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #990000;">current</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">!==</span> <span style="color: #009900; font-weight: bold;">FALSE</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: #009933; font-style: italic;">/** DEMO */</span>
<span style="color: #000088;">$data</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: #339933;">,</span> <span style="color: #cc66cc;">4</span><span style="color: #339933;">,</span> <span style="color: #cc66cc;">5</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$sa</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> sample<span style="color: #009900;">&#40;</span><span style="color: #000088;">$data</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #b1b100;">foreach</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$sa</span> <span style="color: #b1b100;">AS</span> <span style="color: #000088;">$key</span> <span style="color: #339933;">=&gt;</span> <span style="color: #000088;">$row</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #b1b100;">echo</span> <span style="color: #000088;">$key</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">' '</span><span style="color: #339933;">,</span> <span style="color: #000088;">$row</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'&lt;br /&gt;'</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></td></tr></table></div>

<p>在next()方法的实现时有过纠结，一直以为这里需要返回下一个的值，<br />
这是因为一直以为这里的next就是next函数的实现，但是非也<br />
在手册中我们可以看到其定义为<br />
<strong>abstract public void Iterator::next ( void )</strong><br />
其返回值类型为<strong>void</strong><br />
所以这里我们调用next函数就可以了，没有必要返回<br />
另外，以上实现对于如下的数组是存在的问题<br />
$data = array(&#8217;0&#8242; => 11, &#8221; => 22, &#8216;s3&#8242; => 33, 0, 0, &#8221;, false, 0, 1);<br />
运行结果是输出：<br />
0 11<br />
22<br />
s3 33<br />
1 0<br />
2 0<br />
3<br />
false后面的值就没有迭代显示出来了，具体原因还不清楚，留作下回分解<br />
在yii框架中也有实现迭代器，它的实现避免了这个问题。<br />
<br />
【Yii框架中的迭代器实现】<br />
在Yii框架中的我们可以看到其迭代器的实现<br />
在collections目录下的CMapIterator.php文件中，其实现如下：</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
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
</pre></td><td class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">class</span> CMapIterator implements Iterator <span style="color: #009900;">&#123;</span>
<span style="color: #009933; font-style: italic;">/**
* @var array the data to be iterated through
*/</span>
    <span style="color: #000000; font-weight: bold;">private</span> <span style="color: #000088;">$_d</span><span style="color: #339933;">;</span>
<span style="color: #009933; font-style: italic;">/**
* @var array list of keys in the map
*/</span>
    <span style="color: #000000; font-weight: bold;">private</span> <span style="color: #000088;">$_keys</span><span style="color: #339933;">;</span>
<span style="color: #009933; font-style: italic;">/**
* @var mixed current key
*/</span>
    <span style="color: #000000; font-weight: bold;">private</span> <span style="color: #000088;">$_key</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #009933; font-style: italic;">/**
* Constructor.
* @param array the data to be iterated through
*/</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: #339933;">&amp;</span><span style="color: #000088;">$data</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_d<span style="color: #339933;">=&amp;</span><span style="color: #000088;">$data</span><span style="color: #339933;">;</span>
        <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_keys<span style="color: #339933;">=</span><span style="color: #990000;">array_keys</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$data</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #009933; font-style: italic;">/**
* Rewinds internal array pointer.
* This method is required by the interface Iterator.
*/</span>
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> <span style="color: #990000;">rewind</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>                                                                                 
        <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_key<span style="color: #339933;">=</span><span style="color: #990000;">reset</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_keys<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #009933; font-style: italic;">/**
* Returns the key of the current array element.
* This method is required by the interface Iterator.
* @return mixed the key of the current array element
*/</span>
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> <span style="color: #990000;">key</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #b1b100;">return</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_key<span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #009933; font-style: italic;">/**
* Returns the current array element.
* This method is required by the interface Iterator.
* @return mixed the current array element
*/</span>
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> <span style="color: #990000;">current</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #b1b100;">return</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_d<span style="color: #009900;">&#91;</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_key<span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #009933; font-style: italic;">/**
* Moves the internal pointer to the next array element.
* This method is required by the interface Iterator.
*/</span>
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> <span style="color: #990000;">next</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_key<span style="color: #339933;">=</span><span style="color: #990000;">next</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_keys<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #009933; font-style: italic;">/**
* Returns whether there is an element at current position.
* This method is required by the interface Iterator.
* @return boolean
*/</span>
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> valid<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #b1b100;">return</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_key<span style="color: #339933;">!==</span><span style="color: #009900; font-weight: bold;">false</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #000088;">$data</span> <span style="color: #339933;">=</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'s1'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #cc66cc;">11</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'s2'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #cc66cc;">22</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'s3'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #cc66cc;">33</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$it</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> CMapIterator<span style="color: #009900;">&#40;</span><span style="color: #000088;">$data</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #b1b100;">foreach</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$it</span> <span style="color: #b1b100;">as</span> <span style="color: #000088;">$row</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #b1b100;">echo</span> <span style="color: #000088;">$row</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'&lt;br /&gt;'</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></td></tr></table></div>

<p>这与之前的简单实现相比，其位置的变化是通过控制key来实现的，这种实现的作用是为了避免false作为数组值时无法迭代</p>
]]></content:encoded>
			<wfw:commentRss>https://www.phppan.com/2010/04/php-iterator-and-yii-cmapiterator/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
