PHPthink
search in  



  • 本站技术文章大部分为个人原创,若需要转载,请注名出处。少数转发的文章或则翻译的文章都会被标识。

深入讨论PHP5对象复制技术

[原创文章]发布时间:[2008-08-10 11:38:03]

此文将由浅入深的讨论PHP5的对象复制技术  原创文章 请尊重版权  有错误或则不当之处还希望能够指出来

对象复制的由来

为什么对象会有“复制”这个概念,这与PHP5中对象的传值方式是密切相关的,让我们看看下面这段简单的代码

 

PHP代码
 
  1. /** 
  2.  * 电视机类 
  3.  */  
  4. class Television   
  5. {  
  6.     /** 
  7.      * 屏幕高度 
  8.      */  
  9.     protected $_screenLength = 300;  
  10.       
  11.     /** 
  12.      * 屏幕宽度 
  13.      */  
  14.     protected $_screenHight  = 200;  
  15.       
  16.     /** 
  17.      * 电视机外观颜色 
  18.      */  
  19.     protected $_color        = 'black';  
  20.       
  21.     /** 
  22.      * 返回电视外观颜色 
  23.      */  
  24.     public function getColor()  
  25.     {  
  26.         return $this->_color;  
  27.     }  
  28.       
  29.     /** 
  30.      * 设置电视机外观颜色 
  31.      */  
  32.     public function setColor($color)  
  33.     {  
  34.         $this->_color = (string)$color;  
  35.         return $this;  
  36.     }  
  37. }  
  38.   
  39. $tv1 = new Television();  
  40. $tv2 = $tv1;  

这段代码定义了一个电视机的类 Television , $tv1为一个电视机的实例,然后我们按照普通的变量赋值方式将$tv1的值赋给$t2。那么现在我们拥有两台电视机$tv1和$tv2了,真的是这样的吗?我们来测试一下。

 

PHP代码
 
  1. echo 'color of tv1 is: ' . $tv1->getColor();//tv1的颜色是black  
  2. echo '<br>';  
  3. echo 'color of tv2 is: ' . $tv2->getColor();//tv2的颜色是black  
  4. echo '<br>';  
  5.   
  6. //把tv2涂成白色  
  7. $tv2->setColor('white');  
  8.   
  9. echo 'color of tv2 is: ' . $tv2->getColor();//tv2的颜色是white  
  10. echo '<br>';  
  11. echo 'color of tv1 is: ' . $tv1->getColor();//tv1的颜色是white  

 首先我们看到tv1和tv2的颜色都是black,现在我们希望tv2换个颜色,所以我们将它的颜色设置成了white,我们再看看tv2的颜色,确实成为了white,似乎满足了我们的要求,可是并没有想象中的那么顺利,当我们接着看tv1的颜色的时候,我们发现tv1也由black边成了white。我们并没有重新设置tv1的颜色,为什么tv1会重black变成white呢?这是因为PHP5中对象的赋值和传值都是以“引用”的方式。PHP5使用了Zend引擎II,对象被储存于独立的结构Object Store中,而不像其它一般变量那样储存于Zval中(在PHP4中对象和一般变量一样存储于Zval)。在Zval中仅存储对象的指针而不是内容(value)。当我们复制一个对象或者将一个对象当作参数传递给一个函数时,我们不需要复制数据。仅仅保持相同的对象指针并由另一个zval通知现在这个特定的对象指向的Object Store。由于对象本身位于Object Store,我们对它所作的任何改变将影响到所有持有该对象指针的zval结构----表现在程序中就是目标对象的任何改变都会影响到源对象。.这使PHP对象看起来就像总是通过引用(reference)来传递。所以以上的tv2和tv1其实是指向同一个电视机实例,我们对tv1或则tv2所做的操作其实都是针对这同一个实例。因此我们的“复制”失败了。看来直接变量赋值的方式并不能拷贝对象,为此PHP5提供了一个专门用于复制对象的操作,也就是 clone 。这就是对象复制的由来。

...

全文 | 评论: 2 条 | 分类:OOP


Zend Framework 的 PHP 编码标准

发布时间:[2008-08-03 15:36:24] 最后更新:[2008-08-03 15:47:39]

关于编码标准的利与弊我这里不再介绍,想要了解的可以用搜索引擎搜索此关键字。PHP官方一直都没有制定任何PHP编码规范,一般都是公司或则团队内部自己来定义规范。Zend Framework作为一款优秀的PHP官方框架,有着非常良好的编码规范,我相信这套规范也带有一定的官方性质,让你的团队成员认真阅读并遵循此规范,我们一样能写出Zend framework这样漂亮整洁可读性强的代码。您可以在Zend Framework的中文文档中到到此规范。感谢Zend Framework中文团队。(此段概述由本文发布者添加)

B.1. 绪论

B.1.1. 适用范围

本文档提供的代码格式和文档的指南是给参与 Zend Framework 的个人和团队使用的,许多使用 Zend Framework 的开发者 也发现编码标准很有用,因为他们的代码风格和 Zend Framework 的代码保持一致。值得注意的是它要求切实努力来全面 详细说明编码标准。 注:有时候开发者认为在最详细的设计级别上标准的建立比标准所建议的更重要。Zend Framework 编码标准的指南 实践上很好地工作于 ZF 项目。你可以根据我们的 license 中的条款来修改或使用它们。

ZF 编码标准的话题包括:

  • PHP File 文件格式

  • 命名约定

  • 编码风格

  • 注释文档

 

B.1.2. 目标

编码标准对任何开发项目都很重要,特别是很多开发者在同一项目上工作。编码标准帮助确保代码的高质量、少 bug 和容易维护。

...

全文 | 评论: 0 条 | 分类:PHP


推荐PHP5面向对象入门教材

[原创文章]发布时间:[2008-07-02 22:43:24] 最后更新:[2008-07-02 22:53:23]

    对于初学PHP5面向对象的朋友们,我推荐刀客羽朋前辈的原创教材《php5 面向对象》,06年的时候还没有几本专门介绍PHP5面向对象的教材,刀客羽朋前辈的这本教材模仿了JAVA教材(他本人为JAVA讲师)并且结合了PHP本身的一些特性,非常仔细全面的介绍了PHP5的面向对象基础以及少量设计模式,已经有无数PHPER通过阅读此书走上了面向对象设计之路,我也是其中之一。初学者精读此书必受益非浅。此书没有印刷版,只有PDF版本提供下载,全书一共五章,我将内容直接放到了我的站内,方便大家阅读和评论。

前言:

    从OOP的视角看,不应区分语言。无论是C++、无论是Java、无论是.net还有更多面向对象的语言,只要你了解了OO的真谛,便可以跨越语言,让你的思想轻松的跳跃。便没有对于Java、.net 、 PHP 之间谁强谁弱的争执了。
    希望这个介绍PHP5面向对象编程(OOP)的资料能让初学者受益,能让更多的PHPer开始转向OO的编程过程。相对PHP4,PHP5在面向对象方面改变了很多。我们将只介绍PHP5环境下的面向对象。而我们必须改变自己来跟随PHP5的发展。如果代码结果在你的环境下执行不一致,请确认你的环境为PHP5。
    我们假设读者没有任何面向对象的知识,即使你是第一次听说OOP,也可以读懂这文章。但我希望你必须对PHP有一些了解。
    在后面我们将使用一些例子,来逐渐分析PHP5的OO基础。
    面向对象只解决了两个问题,代码的可扩展性 、 代码的可维护性。
    关于为什么要使用面向对象?在什么时候使用面向对象?这里不讨论。

   ........

...

全文 | 评论: 2 条 | 分类:others


为什么子类重写父类方法时访问权限不能比父类低?

[原创文章]发布时间:[2008-06-02 21:29:18] 最后更新:[2008-06-02 21:30:16]

    前一段时间,论坛的一位网友遇到了这样一个问题。此问题相关的代码如下:(PHP版本5及以上)

PHP代码
 
  1. class b {   
  2.     public function __construct() {   
  3.         //   
  4.     }   
  5. }   
  6.   
  7. class a extends b {   
  8.     private static $instance = NULL;   
  9.        
  10.     private function __construct() {   
  11.         parent::__construct();   
  12.     }   
  13.        
  14.     public static function getInstance() {   
  15.         if (self::$instance === NULL) {   
  16.             self::$instance = new a();   
  17.         }   
  18.         return self::$instance;   
  19.     }   
  20.        
  21.     public function test() {   
  22.         echo "success";   
  23.     }   
  24. }   
  25.   
  26. $foo = a::getInstance();   
  27. $foo->test();  

    现有一个类b,他用a继承b类,他又希望a的所有实例能保持单一,所以他打算让a类实现单例模式(关于单例模式以后会专门写一篇文章讨论,如果你不懂这个概念,请直接搜索)。此想法似乎没有任何不妥之处,然后代码运行之后,程序报了错:...

全文 | 评论: 10 条 | 分类:OOP


向Zend Framework Issue Tracker提交了一个小BUG

[原创文章]发布时间:[2008-05-23 11:22:02] 最后更新:[2008-05-23 11:27:32]

    最近在研究Zend Framework的DB模块源代码,发现Zend_Db_Table_Row_Abstract类中存在一个隐藏着的BUG,并且自己做了相关测试,确实可能会出现问题,虽然遇到这个问题的几率不是很高,并且不会造成致命的威胁,但是一旦遇到这个问题很难察觉。于是向Zend Framework Issue Tracker提交了此BUG,源码版本为1.5.2,也就是最新版。
   与这个BUG相关的代码如下:

PHP代码
 
  1. abstract class Zend_Db_Table_Row_Abstract  
  2. {  
  3.   
  4.     /** 
  5.      * The data for each column in the row (column_name => value). 
  6.      * The keys must match the physical names of columns in the 
  7.      * table for which this row is defined. 
  8.      * 
  9.      * @var array 
  10.      */  
  11.     protected $_data = array();  
  12.      
  13.     //...................  
  14.   
  15.   
  16.     /** 
  17.      * Retrieve row field value 
  18.      * 
  19.      * @param  string $columnName The user-specified column name. 
  20.      * @return string             The corresponding column value. 
  21.      * @throws Zend_Db_Table_Row_Exception if the $columnName is not a column in the row. 
  22.      */  
  23.     public function __get($columnName)  
  24.     {  
  25.         $columnName = $this->_transformColumn($columnName);  
  26.         if (!array_key_exists($columnName$this->_data)) {  
  27.             require_once 'Zend/Db/Table/Row/Exception.php';  
  28.             throw new Zend_Db_Table_Row_Exception("Specified column \"$columnName\" is not in the row");  
  29.         }  
  30.         return $this->_data[$columnName];  
  31.     }  
  32.   
  33.     /** 
  34.      * Set row field value 
  35.      * 
  36.      * @param  string $columnName The column key. 
  37.      * @param  mixed  $value      The value for the property. 
  38.      * @return void 
  39.      * @throws Zend_Db_Table_Row_Exception 
  40.      */  
  41.     public function __set($columnName$value)  
  42.     {  
  43.         $columnName = $this->_transformColumn($columnName);  
  44.         if (!array_key_exists($columnName$this->_data)) {  
  45.             require_once 'Zend/Db/Table/Row/Exception.php';  
  46.             throw new Zend_Db_Table_Row_Exception("Specified column \"$columnName\" is not in the row");  
  47.         }  
  48.         $this->_data[$columnName] = $value;  
  49.         $this->_modifiedFields[$columnName] = true;  
  50.     }  
  51.   
  52.    //.................  
  53.   
  54.     /** 
  55.      * Sets all data in the row from an array. 
  56.      * 
  57.      * @param  array $data 
  58.      * @return Zend_Db_Table_Row_Abstract Provides a fluent interface 
  59.      */  
  60.     public function setFromArray(array $data)  
  61.     {  
  62.         foreach ($data as $columnName => $value) {  
  63.             $this->$columnName = $value;  
  64.         }  
  65.   
  66.         return $this;  
  67.     }  
  68.   
  69.   
  70.     //...........  
  71. }  

    于此BUG相关的两个方法为__set() 和 setFromArray,其中__set()为魔术方...

全文 | 评论: 3 条 | 分类:ZendFramework







(c)2007-2008 PHPthink.com   玉面修罗. All rights reserved.