php5中魔术方法学习笔记

1.__construct() 当实例化一个对象的时候,这个对象的这个方法首先被调用.

PHP实例代码如下:

  1. class Test { function __construct() { echo "before"; } } $t = new Test();
  2. class Test { function __construct() { echo "before"; } } $t = new Test();
  3. //输出是:start

构造器是一个魔术方法,当对象被实例化时它会被调用,在一个类声明时它常常是第一件做的事但是没得必要他也像其他任何方法在类中任何地方都可以声明,构造器也能像其他方法样继承,如果我们想到以前继承例子从介绍到oop,我们能添加构造方法到Animal 类中.

代码如下:

  1. class Animal{
  2. public function __construct() {
  3. $this->created = time();
  4. $this->logfile_handle = fopen('/tmp/log.txt', 'w');
  5. }
  6. }

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

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

我们知道php5对象模型和类名相同的函数是类的构造函数,那么如果我们同时定义构造函数和__construct()方法的话,php5会默认调用构造函数而不会调用__construct()函数,所以__construct()作为类的默认的构造函数 .

2.__destruct() 当删除一个对象或对象操作终止的时候,调用该方法.代码如下:

  1. class Test { function __destruct() { echo "end"; } } $t = new Test();//将会输出end
  2. class Test { function __destruct() { echo "end"; } } $t = new Test();//将会输出end

我们就可以在对象操作结束的时候进行释放资源之类的操作

3.__get() 当试图读取一个并不存在的属性的时候被调用.

如果试图读取一个对象并不存在的属性的时候,PHP就会给出错误信息,如果在类里添加__get方法,并且我们可以用这个函数实现类似java中反射的各种操作.代码如下:

  1. class Test { public function __get($key) { echo $key . " 不存在"; } } $t = new Test(); echo $t->name; 就会输出:name 不存在
  2. class Test { public function __get($key) { echo $key . " 不存在"; } } $t = new Test(); echo $t->name; 就会输出:name 不存在

例子代码如下:

  1. class Penguin extends Animal {
  2. public function __construct($id) {
  3. $this->getPenguinFromDb($id);
  4. }
  5. public function getPenguinFromDb($id) {
  6. }
  7. }

4.__set() 当试图向一个并不存在的属性写入值的时候被调用,代码如下:

  1. class Test { public function __set($key,$value) { echo '对'.$key . "附值".$value; } } $t = new Test(); $t->name = "aninggo"; 就会输出:对 name 附值 aninggo
  2. class Test { public function __set($key,$value) { echo '对'.$key . "附值".$value; } } $t = new Test(); $t->name = "aninggo"; 就会输出:对 name 附值 aninggo

5.__call() 当试图调用一个对象并不存在的方法时,调用该方法,代码如下:

  1. class Test { public function __call($Key, $Args) { echo "您要调用的 {$Key} 方法不存在。你传入的参数是:" . print_r($Args, true); } } $t = new Test(); $t->getName(aning,go);
  2. class Test { public function __call($Key, $Args) { echo "您要调用的 {$Key} 方法不存在。你传入的参数是:" . print_r($Args, true); } } $t = new Test(); $t->getName(aning,go);
  3. 程序将会输出:您要调用的 getName 方法不存在。参数是:Array
  4. (
  5. [0] => aning
  6. [1] => go
  7. )
  8. 您要调用的 getName 方法不存在。参数是:Array
  9. (
  10. [0] => aning
  11. [1] => go
  12. )

6.__toString() 当打印一个对象的时候被调用,这个方法类似于java的toString方法,当我们直接打印对象的时候回调用这个函数,代码如下:

  1. class Penguin {
  2. public function __construct($name) {
  3. $this->species = 'Penguin';
  4. $this->name = $name;
  5. }
  6. public function __toString() {
  7. return $this->name . " (" . $this->species . ")n";
  8. }
  9. }

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

$tux = new Penguin('tux');echo $tux;

7.__clone()

我们看过一个使用clone关键字的例子,在我的介绍从入门到oop的第二部分,创建对象的副本,而不是有两个变量指向同一个实际的数据,在一个类中重写此方法,我们可以观察发生了什么当在对象上使用clone关键字时,虽然这是不是我们每一天能遇到的,一个漂亮的用例是创建一个真正的单例模式通过添加private访问修饰符给这个方法,代码如下:

class Test { public function __clone() { echo "我被复制了!"; } }$t = new Test(); $t1 = clone $t;程序输出:我被克隆了!

__sleep

__sleep()方法会被调用当对象被序列化后,并允许你处理序列化。这有各种各样的程序,一个很好的例子如果一个对象包含某种类型的指针,例如文件句柄或引用另一个对象。当对象被序列化然后解序列化,这些引用类型是无用的,因为这些类型的引用的目标可能不再存在或有效。因此,最好是来取消这些信息在存储它们之前。

__wakeup

__wakeup()是与__sleep()方法相反的,允许您更改对象解序列化的行为,和__sleep()一起使用,可以用来恢复被删除的句柄和对象当对象被序列化时,一个很好的例子程序是数据库句柄被取消设置当该项被序列化,然后恢复到当前配置中设置项目时,解序列化一个数据库句柄.

__autoload()方法可

比如我们将上面的那个Person类所在的文件定义为 Person_class.php,再新建一个php文件 test.php,编辑内容:

  1. function __autoload($calssName)
  2. {
  3. include $className.”_class.php”; //看到这也许你就明白了吧?哈哈
  4. }
  5. $p = new Person(“mifan”, 22);
  6. $p->say();

这样执行该test.php页面就不会出现错误了.

php魔术方法一般在什么情况下需要使用?

举个简单的例子,当类里面没有属性$name;但是你不小心访问这个属性,这个时候就会出错,但是让你可以设置魔术方法__get($name){ return $name ."不存在"};就会自动调用__get($name);这样程序就会不因为你访问了一个不存在的属性报错而中断执行.

补充下 __get($v) 访问未定义的属性时调用.

__set($v) ?未定义的属性赋值时调用.

__isset($v)对未定义的属性使用isset()函数时调用.

__unset($v)和isset($v)类似.

__call($method)访问未定义的方法是被调用.