6.0 自动加载及魔术方法
6.1 自动加载
在PHP开发过程中,如果希望从外部引入一个class.通常会使用incluae和requre方法把定义这个class的文件包含进来。但是,在大型的开发项目中,这么做会产生大量的require或者include方法的使用。这样不仅会降低效率,并且使代码难以维护。
如果不小心忘记引入某个类的定又文件,PHP就会报告一个致命错误,导致整个应用程序崩溃。
为了解决上述问题,PHP提供了类的自动加载机制,即定义一个_ autoload()函数,它会在试图使用尚未被定义的类时自动调用。
这样,PHP在报告错误之前会有最后一个机会加载所需的类。为了方便理解自动加载机制,接下来通过一个案例来说明_autoload()是 如何实现自动加载的。
首先在当前目录下,定义类文件MyClass1.cass.php.示例代码如下:
1 <?php 2 class MyClass1{ 3 4 } 5 ?>
定义类文件MyClass2.cass.php.示例代码如下:
1 <?php 2 class MyClass2{ 3 4 } 5 ?>
需要注意的是,对于类定义文件,通常使用 类名 .class.php 这种形式的文件名,这样便于程序的编写。
__autoload()方法的使用如例6-16所示
例6-16
1 <?php 2 function __autoload($classname){ 3 require_once $classname . ".class.php"; 4 } 5 $obj1 = new MyClass1(); 6 $obj2 = new MyClass2(); 7 var_dump($obj1); 8 var_dump($obj2); 9 ?>
运行结果
从上图中可以看出试览器并没有访问过这两个类定义文件,在代码中也没有使用include (或requre)将其包含,但是却获得了这两个类的对象。由此说明,__autolad() 函数可以实现自动加载功能。
需要注意的是,自动加载是指当需要类定义文件而没有找到时,会自动的调用_autolad函数,它不只限于实例化对象,还包括继承、序列化等操作。
而且, 自动加载并不能自己完成加载类的功能,它只提供了一个时机。具体的加载代码还需要我们自己编写代码实现。
除了__autoload()函数之外,spl_autoload_regiser()提供了一种更加灵活的方式来实现类的自动加载。
例6-17
1 <?php 2 function loader($classname){ 3 require $classname . ".class.php"; 4 } 5 spl_autoload_register('loader'); 6 $obj1 = new MyClass1(); 7 $obj2 = new MyClass2(); 8 var_dump($obj1); 9 var_dump($obj2); 10 ?>
运行结果
由此证明 spl_autoload_register() 也可以实现类的自动加载
6.2 魔术方法
PHP中有很多以两个下划线开头的方法.如前面介绍的_ _construct() __autolad() _get() 和_ set(). 这些方法被称为魔术方法。
魔术方法有一个特点就是不需要手动调用,在某一时刻会自动执行。为程序的开发带来了极大的便利。
在PHP中提供了多个魔术方法、接下来列举这些常用的度术方法。如下表 所示
方法声明 | 功能描述 |
__sleep() | 对象序列化之前被调用,使程序延缓一段时间执行。 |
__wakeup() | 对象序列化之前被调用,还原被序列化的对象。 |
__toString() | 输出一个对象时被调用,将对象转化为字符串。 |
__call() | 在对象中调用一个不可访问方法时会被调用。 |
__callStatic() | 用静态方式中调用一个不可访问方法时会被调用。 |
__clone() | 克隆对象时被调用。 |
__invoke() | 当尝试以调用函数的方式调用一个对象时被调用 |
上表中列举了PHP中的常用的魔术方法,这些方法在实际开发中会经常的使用,接下来以__toString() 为例 演示一下。
例6-18
1 <?php 2 class Person{ 3 private $name = "张三"; 4 private $age = 21; 5 public function __toString(){ 6 return "$this->name ($this->age)"; 7 } 8 } 9 $p1 = new Person(); 10 echo $p1; 11 ?>
运行结果
张三 (21)