PHP的魔术变量及魔术方法
2015-12-18 17:01
525 查看
PHP魔术变量及魔术方法
有八个魔术常量它们的值随着它们在代码中的位置改变而改变。
__LINE__
__FILE__
__DIR__
__FUNCTION__
__CLASS__
__TRAIT__
__METHOD__
__NAMESPACE__
这些'魔术'方法拥有者特殊的名字,以两个下划线开始,表示这些方法在php特定事件下将会被触发。这可能听起来有点自动魔法但是它真的很酷的,我们已经看过一个简单的例子在lastpost,即我们使用一个构造器-使用这个作为我们第一个例子
__construct
构造器是一个魔术方法,当对象被实例化时它会被调用。在一个类声明时它常常是第一件做的事但是没得必要他也像其他任何方法在类中任何地方都可以声明,构造器也能像其他方法样继承。如果我们想到以前继承例子从介绍到oop,我们能添加构造方法到Animal类中,如:
现在我们创建一个类来继承Animal类-Penguin类!不添加任何属性和方法在Penguin类中,我们能申明并定义它继承自Animal类,如:
如果我们定义一个构造方法在Penguin类中,然后Penguin对象将会运行当它被实例化后。由于并没有构造方法,PHP会参考父类方法定义
信息来使用它因此我们能覆盖父类方法,或者不,在我们的新类中-很便利。
析构器让我们关闭任何额外的资源比如被使用过的对象。在php中由于我们有这样运行时间短的脚本(留意在更新的php版本中增强的垃圾回收机制),通常讨论内存溢出根本不需要。然而它仍是好的推行方法来清理而且总体上让程序运行起来更高效。
现在,如果我们的小企鹅有一个"name"属性,而在此之后加载的属性为"age",那么我们可以这样处理:
然而,设想一下,后端数据库或数据供应者发生了改变,"name"没有了,变味了"username"。并且设想这是一个非常复杂的应用,而需要修改的调用"name"的地方非常多。我们可以使用__get方法,使得"name"属性如同存在一样:
这并不是编写整个系统的好方法,因为它会让调试工作变得更困难,但它是一个非常有价值的工具。它允许如同属性一样使用或者展示需要经过计算的数据,以及无数我都想不到的地方。
这样,我们就针对大量的调用伪造对象的属性,正如我说的,这并不是一个正统的方法,但却是一个很有用的技巧,值得记住。
PHPFatalerror:CalltoundefinedmethodPenguin::speak()in...
通过定义__call方法,我们可以使用一些更友善的提示信息来代替PHP的错误提示:
这将捕获的错误并回应。在实际应用中,更合适的方法是依据你的需要纪录消息日志·,将用户重定向,或者抛出一个异常,但概念是相同的。在这里你可以处理任何你需要处理的不当调用,你可以检测方法的名称,并一一处理——例如,你可以同上面我们重命名属性一些样重命名方法。
在适当的位置,输出该对象通过调用echo输出它,如:
我不常常使用这种捷径,但是知道它的存在是很有用的。
更多魔术方法
更多参考http://php.net,列出的所有的魔术方法(是的。不仅仅是文中所列出的,我仅仅选出那些我认为最好开始学习的)如果你想了解其他请仔细查看
本文地址:http://www.oschina.net/translate/9-magic-methods-in-php
原文地址:www.lornajane.net/posts/2012/9-magic-methods-in-php
本文中的所有译文仅用于学习和交流目的,转载请务必注明文章译者、出处、和本文链接
我们的翻译工作遵照
CC协议,如果我们的工作有侵犯到您的权益,请及时联系我们
有八个魔术常量它们的值随着它们在代码中的位置改变而改变。
__LINE__
__FILE__
__DIR__
__FUNCTION__
__CLASS__
__TRAIT__
__METHOD__
__NAMESPACE__
PHP中的9个魔术方法
这个标题有点牵强因为php有不只9种魔术方法,但是这些将会引导你使用php魔术方法一个好的开始。它可能魔幻,但是并不需要魔杖。这些'魔术'方法拥有者特殊的名字,以两个下划线开始,表示这些方法在php特定事件下将会被触发。这可能听起来有点自动魔法但是它真的很酷的,我们已经看过一个简单的例子在
__construct
构造器是一个魔术方法,当对象被实例化时它会被调用。在一个类声明时它常常是第一件做的事但是没得必要他也像其他任何方法在类中任何地方都可以声明,构造器也能像其他方法样继承。如果我们想到以前继承例子从介绍到oop,我们能添加构造方法到Animal类中,如:1 | class Animal{ |
2 |
3 | public function __construct(){ |
4 | $this ->created=time(); |
5 | $this ->logfile_handle= fopen ( '/tmp/log.txt' , 'w' ); |
6 | } |
7 |
8 | } |
1 | class Penguin extends Animal{ |
2 |
3 | } |
4 |
5 | $tux = new Penguin; |
6 | echo $tux ->created; |
信息来使用它因此我们能覆盖父类方法,或者不,在我们的新类中-很便利。
__destruct
你发现文件句柄也是构造器一部分吗?当我们使用完一个对象时真不想把事情放一边,因此析构方法做着与构造方法相反的事情。当对象被销毁时,析构方法会运行,或者明确的说当我们不再使用它时,php会为我们清理掉。Animal类中,我们的析构方法像这样,如:01 | class Animal{ |
02 |
03 | public function __construct(){ |
04 | $this ->created=time(); |
05 | $this ->logfile_handle= fopen ( '/tmp/log.txt' , 'w' ); |
06 | } |
07 |
08 | public function __destruct(){ |
09 | fclose( $this ->logfile_handle); |
10 | } |
11 | } |
__get
这个魔术方法是一个非常灵巧的小技巧-它使实际上不存在的属性如同存在一半。让我们举个小企鹅的例子:01 | class Penguin extends Animal{ |
02 |
03 | public function __construct( $id ){ |
04 | $this ->getPenguinFromDb( $id ); |
05 | } |
06 |
07 | public function getPenguinFromDb( $id ){ |
08 | //elegantandrobustdatabasecodegoeshere |
09 | } |
10 | } |
1 | $tux = new Penguin(3); |
2 | echo $tux ->name. "is" . $tux ->age. "yearsold\n" ; |
01 | class Penguin extends Animal{ |
02 |
03 | public function __construct( $id ){ |
04 | $this ->getPenguinFromDb( $id ); |
05 | } |
06 |
07 | public function getPenguinFromDb( $id ){ |
08 | //elegantandrobustdatabasecodegoeshere |
09 | } |
10 |
11 | public function __get( $field ){ |
12 | if ( $field == 'name' ){ |
13 | return $this ->username; |
14 | } |
15 | } |
__set
那么,我们将所有对$this->name的调用都更改为返回$this->username的值,那么,如果我们想要设置这个值呢?也许我们有一个账户界面允许用户修改他们的名字。这时我们就需要__set方法的帮助了,举例说明:01 | class Penguin extends Animal{ |
02 |
03 | public function __construct( $id ){ |
04 | $this ->getPenguinFromDb( $id ); |
05 | } |
06 |
07 | public function getPenguinFromDb( $id ){ |
08 | //elegantandrobustdatabasecodegoeshere |
09 | } |
10 |
11 | public function __get( $field ){ |
12 | if ( $field == 'name' ){ |
13 | return $this ->username; |
14 | } |
15 | } |
16 |
17 | public function __set( $field , $value ){ |
18 | if ( $field == 'name' ){ |
19 | $this ->username= $value ; |
20 | } |
21 | } |
22 | } |
__call
这里有两种近似的方法,我并没有单独列出来,而是一起说明。一个是_call方法,如果定义,它将在调用未定义过的方法时被调用;另一个是_callStatic方法,工作方式与第一个相同,但却是在调用未定义的静态方法时生效(PHP5.3加入).通常我使用__call进行友善的错误处理,这在需要别人整合调用你的方法的库代码中非常有用。例如,如果一段脚本拥有一个企鹅对象,名为$penguin,它包含一个$penguin->speak()方法...假设speak()方法没有定义,那么正常情况下我们会看到:PHPFatalerror:CalltoundefinedmethodPenguin::speak()in...
通过定义__call方法,我们可以使用一些更友善的提示信息来代替PHP的错误提示:
01 | class Animal{ |
02 | } |
03 | class Penguin extends Animal{ |
04 |
05 | public function __construct( $id ){ |
06 | $this ->getPenguinFromDb( $id ); |
07 | } |
08 |
09 | public function getPenguinFromDb( $id ){ |
10 | //elegantandrobustdatabasecodegoeshere |
11 | } |
12 |
13 | public function __get( $field ){ |
14 | if ( $field == 'name' ){ |
15 | return $this ->username; |
16 | } |
17 | } |
18 |
19 | public function __set( $field , $value ){ |
20 | if ( $field == 'name' ){ |
21 | $this ->username= $value ; |
22 | } |
23 | } |
24 |
25 | public function __call( $method , $args ){ |
26 | echo "unknownmethod" . $method ; |
27 | return false; |
28 | } |
29 | } |
__sleep
__sleep()方法会被调用当对象被序列化后,并允许你处理序列化。这有各种各样的程序,一个很好的例子如果一个对象包含某种类型的指针,例如文件句柄或引用另一个对象。当对象被序列化然后解序列化,这些引用类型是无用的,因为这些类型的引用的目标可能不再存在或有效。因此,最好是来取消这些信息在存储它们之前。__wakeup
__wakeup()是与__sleep()方法相反的,允许您更改对象解序列化的行为。和__sleep()一起使用,可以用来恢复被删除的句柄和对象当对象被序列化时。一个很好的例子程序是数据库句柄被取消设置当该项被序列化,然后恢复到当前配置中设置项目时,解序列化一个数据库句柄。__clone
我们看过一个使用clone关键字的例子,在我的介绍从入门到oop的第二部分,创建对象的副本,而不是有两个变量指向同一个实际的数据。在一个类中重写此方法,我们可以观察发生了什么当在对象上使用clone关键字时,。虽然这是不是我们每一天能遇到的,一个漂亮的用例是创建一个真正的单例模式通过添加private访问修饰符给这个方法。__toString
无疑把最好的始终留到最后,__toString方法是一个非常方便的附加方法对于我们的工具包。该方法可以声明覆盖对象的行为,当作为一个字符串输出时,例如,当它被输出时。如果你想能输出对象到模板中,你可以使用此方法来控制输出结果。让我们再来看看在Penguin类中:01 | class Penguin{ |
02 |
03 | public function __construct( $name ){ |
04 | $this ->species= 'Penguin' ; |
05 | $this ->name= $name ; |
06 | } |
07 |
08 | public function __toString(){ |
09 | return $this ->name. "(" . $this ->species. ")\n" ; |
10 | } |
11 | } |
1 | $tux = new Penguin( 'tux' ); |
2 | echo $tux ; |
更多魔术方法
更多参考本文地址:
原文地址:
本文中的所有译文仅用于学习和交流目的,转载请务必注明文章译者、出处、和本文链接
我们的翻译工作遵照
CC协议,如果我们的工作有侵犯到您的权益,请及时联系我们
相关文章推荐
- PHP PSR规范
- php学习练手(二)
- thinkphp实现163、QQ邮箱收发邮件的方法
- php日历的快捷实现
- cron以及在laravel中使用cron
- yii2 URL %2F and /
- phpize的深入理解
- PHP学习路上的一点心得
- Erlang学习心得
- thinkphp 连接postgresql
- 浅谈Java和PHP的异同
- php 表单提交大量数据发生丢失的解决方法
- php编码
- WordPress中用于更新伪静态规则的PHP代码实例讲解
- PHP Curl出现403错误的解决办法 beecloud webhook订单状态返回 服务器403的问题
- 关于ThinkPHP中$this->redirect的疑问。
- PHP、MySql乱码解决方案
- php学习练手(一)
- Windows上PHP扩展的实现,部署及应用
- PHP魔术方法学习笔记