这个标题有点牵强因为php有不只9种魔术方法, 但是这些将会引导你使用php魔术方法一个好的开始。它可能魔幻,但是并不需要魔杖。 
这些'魔术'方法拥有者特殊的名字,以两个下划线开始,表示这些方法在php特定事件下将会被触发。这可能听起来有点自动魔法但是它真的很酷的,我们已经看过一个简单的例子在 last post,即我们使用一个构造器-使用这个作为我们第一个例子

__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 }

现在我们创建一个类来继承Animal类 - Penguin类!不添加任何属性和方法在Penguin类中,我们能申明并定义它继承自Animal类,如:

1 class Penguin extends Animal {
2   
3 }
4   
5 $tux new Penguin;
6 echo $tux->created;

如果我们定义一个构造方法在Penguin类中,然后Penguin对象将会运行当它被实例化后。由于并没有构造方法,PHP 会参考父类方法定义 信息来使用它因此我们能覆盖父类方法,或者不,在我们的新类中-很便利。

__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 }

析构器让我们关闭任何额外的资源比如被使用过的对象。在php中由于我们有这样运行时间短的脚本(留意在更新的php版本中增强的垃圾回收机制),通常讨论内存溢出根本不需要。然而它仍是好的推行方法来清理而且总体上让程序运行起来更高效。

__get

这个魔术方法是一个非常灵巧的小技巧 - 它使实际上不存在的属性如同存在一半。让我们举个小企鹅的例子:

01 class Penguin extends Animal {
02   
03   public function __construct($id) {
04     $this->getPenguinFromDb($id);
05   }
06   
07   public function getPenguinFromDb($id) {
08     // elegant and robust database code goes here
09   }
10 }

现在,如果我们的小企鹅有一个 "name" 属性,而在此之后加载的属性为 "age",那么我们可以这样处理:

1 $tux new Penguin(3);
2 echo $tux->name . " is " $tux->age . " years old\n";

然而,设想一下,后端数据库或数据供应者发生了改变,"name"没有了,变味了"username"。并且设想这是一个非常复杂的应用,而需要修改的调用"name"的地方非常多。我们可以使用 __get 方法,使得"name"属性如同存在一样:

01 class Penguin extends Animal {
02   
03   public function __construct($id) {
04     $this->getPenguinFromDb($id);
05   }
06   
07   public function getPenguinFromDb($id) {
08     // elegant and robust database code goes here
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     // elegant and robust database code goes here
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 方法,工作方式与第一个相同,但却是在调用未定义的静态方法时生效(PHP 5.3 加入).通常我使用 __call 进行友善的错误处理,这在需要别人整合调用你的方法的库代码中非常有用。例如,如果一段脚本拥有一个企鹅对象,名为 $penguin ,它包含一个 $penguin->speak() 方法...假设 speak() 方法没有定义,那么正常情况下我们会看到:

PHP Fatal error: Call to undefined method Penguin::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     // elegant and robust database code goes here
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 "unknown method " $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 }

在适当的位置,输出该对象通过调用echo输出它,如:

1 $tux new Penguin('tux');
2 echo $tux;

我不常常使用这种捷径,但是知道它的存在是很有用的。

 

更多魔术方法

更多参考 http://php.net, 列出的所有的魔术方法(是的。不仅仅是文中所列出的,我仅仅选出那些我认为最好开始学习的)如果你想了解其他请仔细查看

PHP 中的 9 个魔术方法的更多相关文章

  1. PHP中的11个魔术方法总结:__construct,、__destruct、__call等

    PHP中的魔术方法总结 :__construct, __destruct , __call, __callStatic,__get, __set, __isset, __unset , __sleep ...

  2. PHP中的11个魔术方法

    1.__get.__set 这两个方法是为在类和他们的父类中没有声明的属性而设计的 __get( $property )       当调用一个未定义的属性时访问此方法__set( $property ...

  3. php 中的魔术方法-----“事件方法”

    来源:http://lornajane.net/posts/2012/phps-magic-__invoke-method-and-the-callable-typehint php 中的这个对象 , ...

  4. PHP中常用的魔术方法

    我们在PHP中经常用到魔术方法,像构造方法,析构方法等等魔术变量,下面总结一下一些常用的魔术变量: __construct(),__destruct(),__clone(),__autoload(), ...

  5. PHP 中 16 个魔术方法详解

    PHP 中 16 个魔术方法详解   前言 PHP中把以两个下划线__开头的方法称为魔术方法(Magic methods),这些方法在PHP中充当了举足轻重的作用. 魔术方法包括: __constru ...

  6. 前端学PHP之面向对象系列第二篇——魔术方法

    × 目录 [1]构造方法 [2]析构方法 [3]不可访问属性[4]对象复制[5]字符串[6]对象不存在[7]自动加载类[8]串行化[9]函数调用 前面的话 php在面向对象部分有很多相关的魔术方法,这 ...

  7. PHP面向对象常见的关键字和魔术方法

    在PHP5的面向对象程序设计中提供了一些常见的关键字,用来修饰类.成员属性或成员方法,使他们具有特定的功能,例如final.static.const等关键字.还有一些比较实用的魔术方法,用来提高类或对 ...

  8. php拦截器(魔术方法)

    什么是PHP拦截器? 英文名称 “interceptor”,作用是 拦截 发送未定义的方法和属性的消息. 先看一段代码,定义了一个School类,实例化一个对象$obj,获取一个未定义的属性teach ...

  9. PHP的魔术方法

    PHP中把以两个下划线__开头的方法称为魔术方法(Magic methods) 魔术方法包括: __construct(),类的构造函数 __destruct(),类的析构函数 __call(),在对 ...

随机推荐

  1. WAP调用微信支付https://pay.weixin.qq.com/wiki/doc/api/wap.php?chapter=15_1

    公司做的一个购物网站 之前微信版的网站要搬在webView上   可是微信支付是个问题 , 在外部浏览器怎么都发不起微信请求 , 原因是因为页面调用的微信浏览器自带JSAPI 在外部浏览器无法调用,但 ...

  2. AD组策略添加本地账号、设置允许ping回显

    AD组策略添加本地账号 1. 管理工具--组策略管理--选择相应GPO(编辑)----首选项--控制面板设置--本地用户和组--右键添加账号 2.域成员计算机刷新组策略(gpupdate/force) ...

  3. 测序原理 - PacBio技术资料

    手头有一套完整的PacBio技术资料,会慢慢的总结到博客上. 写在前面:PacBio公司主要有两个测序平台一个是RS,一个是最新的Sequel,下面如果没有指明则是在讲RS平台. SMRT测序技术总览 ...

  4. eclipse 中发布 maven 项目到 tomcat

    第一步:在 eclipse 中 右键  你的项目 Run as --> Maven build...--> Goals: 输入 install   run 第二步:在 eclipse 中 ...

  5. 学习ASP.NET之前,先了解它

    ASP.NET是一个使用HTML,CSS,JavaScript和服务器脚本构建的网页和网站的开发框架,不是一门编程语言. ASP.NET支持三种不同的开发模式:Web Pages(Web页面),MVC ...

  6. JavaScript Table行定位效果

    作者:cloudgamer 时间: 2009-09-17 文档类型:原创 来自:蓝色理想 第 1 页 JavaScript Table行定位效果 [1] 第 2 页 JavaScript Table行 ...

  7. sass less

    CSS 预处理器技术已经非常的成熟,而且也涌现出了越来越多的 CSS 的预处理器框架.本文向你介绍使用最为普遍的三款 CSS 预处理器框架,分别是 Sass.Less CSS.Stylus. 首先我们 ...

  8. 扒一扒JavaScript 预解释

    带var关键字预解释 让我们先看下这段代码执行的结果: 代码如下: alert(n);//弹出undefinedvar n = 10; 弹出的结果是undefined,为何不是10?让我们再看下面这段 ...

  9. Innodb中的事务隔离级别和锁的关系

    前言: 我们都知道事务的几种性质,数据库为了维护这些性质,尤其是一致性和隔离性,一般使用加锁这种方式.同时数据库又是个高并发的应用,同一时间会有大量的并发访问,如果加锁过度,会极大的降低并发处理能力. ...

  10. 小米域名过渡JS

    <script>jQuery(function($) { (function() { var $bnBar = $(''), $topBn = $('#J_topBn'), $topBnB ...