PHP

来源:互联网 发布:中国银行淘宝校园卡 编辑:程序博客网 时间:2024/05/19 13:43

PHP - 魔术方法

本文引用http://www.jb51.net/article/96167.htm

1. __construct() 构造函数

类在实例化时自动调用的方法, 用于类的初始化, 在初始化的时候对该类的成员进行赋值

2. __destruct() 析构函数

在销毁一个类之前执行的一些操作和功能, 比如说关闭文件,释放结果集等.注: 析构函数不能带任何参数

3. __call() 在对象中调用一个不可访问方法时调用

该方法有两个参数,第一个参数 $function_name 会自动接收不存在的方法名,第二个 $arguments 则以**索引**数组的方式接收不存在方法的多个参数为了避免当调用的方法不存在时产生错误,而意外的导致程序中止,可以使用 __call() 方法来避免.该方法在调用的方法不存在时会自动调用,程序仍会继续执行下去。
<?phpclass Person{  /**   * 声明此方法用来处理调用对象中不存在的方法   */  function __call($funName, $arguments)  {      echo "你所调用的函数:" . $funName . "(参数:" ; // 输出调用不存在的方法名     print_r($arguments); // 输出调用不存在的方法时的参数列表     echo ")不存在!<br>\n"; // 结束换行             }                     }$Person = new Person();      $Person->run("teacher"); // 调用对象中不存在的方法,则自动调用了对象中的__call()方法$Person->eat("小明", "苹果");// 输出结果    // 你所调用的函数:run(参数:Array ( [0] => teacher ) )不存在!    // 你所调用的函数:eat(参数:Array ( [0] => 小明 [1] => 苹果 ) )不存在!    // Hello, world!

4. __callStatic() 在对象中调用一个不可访问方法时调用

此方法跟__call()基本一致, 区别在于__callStatic()方法是在类静态调用不存在的方法是自动调用的

5. __clone() 当对象复制完成时调用

作用:对象复制可以通过 clone 关键字来完成(如果可能,这将调用对象的 __clone() 方法)。对象中的 __clone() 方法不能被直接调用。语法:$copy_of_object = clone $object;注意:当对象被复制后,PHP 5 会对对象的所有属性执行一个浅复制(shallow copy)。所有的引用属性 仍然会是一个指向原来的变量的引用。当复制完成时,如果定义了 __clone() 方法,则新创建的对象(复制生成的对象)中的 __clone() 方法会被调用,可用于修改属性的值(如果有必要的话)
<?phpclass Person{  public $sex;  public $name;  public $age;  public function __construct($name="", $age=25, $sex='男')  {    $this->name = $name;    $this->age = $age;    $this->sex = $sex;  }  public function __clone()  {    echo __METHOD__."你正在克隆对象<br>";  }}$person = new Person('小明'); // 初始赋值$person2 = clone $person;var_dump('persion1:');var_dump($person);echo '<br>';var_dump('persion2:');var_dump($person2);//看结果://Person::__clone你正在克隆对象//string(9) "persion1:" object(Person)#1 (3) { ["sex"]=> string(3) "男" ["name"]=> //string(6) "小明" ["age"]=> int(25) } //string(9) "persion2:" object(Person)#2 (3) { ["sex"]=> string(3) "男" ["name"]=> //string(6) "小明" ["age"]=> int(25) }克隆成功。

6. __autoload() 尝试加载未定义的类

/**  * 文件autoload_demo.php  */function __autoload($className) {   $filePath = “project/class/{$className}.php”;   if (is_readable($filePath)) {     require($filePath);   } }if (条件A) {   $a = new A();   $b = new B();   $c = new C();   // … 业务逻辑 } else if (条件B) {   $a = newA();   $b = new B();   // … 业务逻辑 }
当php引擎第一次使用类A,但是找不到时,会自动调用 __autoload 方法,并将类名“A”作为参数传入。所以,我们在 __autoload() 中需要的做的就是根据类名,找到相应的文件,并包含进来,如果我们的方法也找不到,那么php引擎就会报错了。**注意**:这里可以只用require,因为一旦包含进来后,php引擎再遇到类A时,将不会调用__autoload,而是直接使用内存中的类A,不会导致多次包含。**扩展**:其实php发展到今天,已经有将 `spl_autoload_register` — 注册给定的函数作为 __autoload 的实现了,但是这个不在啊本文讲解之内,有兴趣可以自行看手册

7. __get() 获得一个类的成员变量时调用

魔术方法__get()的作用在程序运行过程中,通过它可以在对象的外部获取私有成员属性的值。如果成员属性不封装成私有的,对象本身就不会去自动调用这个方法
<?phpclass Person{  private $name = '周更生';  private $age = '32';  function __construct($name="", $age=1)  {    $this->name = $name;    $this->age = $age;  }  /**   * 在类中添加__get()方法,在直接获取属性值时自动调用一次,以属性名作为参数传入并处理   * @param $propertyName   */  public function __get($propertyName)  {      return $this->$propertyName;  }}$Person = new Person("小明", 60);  // 通过Person类实例化的对象,并通过构造方法为属性赋初值echo "姓名:" . $Person->name . "<br>";  // 直接访问私有属性name,自动调用了__get()方法可以间接获取echo "年龄:" . $Person->age . "<br>";  // 自动调用了__get()方法,根据对象本身的情况会返回不同的值// 运行结果:// 姓名:周更生// 年龄:32

8. __set() 设置一个类的成员变量时调用

__set( $property, $value ) 方法用来设置私有属性, 给一个未定义的属性赋值时,此方法会被触发,传递的参数是被设置的属性名和值
<?phpclass Person{  private $name;  private $age;  public function __construct($name="", $age=25)  {    $this->name = $name;    $this->age = $age;  }  /**   * 声明魔术方法需要两个参数,真接为私有属性赋值时自动调用,并可以屏蔽一些非法赋值   * @param $property   * @param $value   */  public function __set($property, $value) {    if ($property=="age")    {      if ($value > 150 || $value < 0) {        return;      }    }    $this->$property = $value;  }  /**   * 在类中声明说话的方法,将所有的私有属性说出   */  public function say(){    echo "我叫".$this->name.",今年".$this->age."岁了";  }}$Person=new Person("小明", 25); //注意,初始值将被下面所改变//自动调用了__set()函数,将属性名name传给第一个参数,将属性值”李四”传给第二个参数$Person->name = "小红";   //赋值成功。如果没有__set(),则出错。//自动调用了__set()函数,将属性名age传给第一个参数,将属性值26传给第二个参数$Person->age = 16; //赋值成功$Person->age = 160; //160是一个非法值,赋值失效$Person->say(); //输出:我叫小红,今年16岁了

9. __isset(),当对不可访问属性调用isset()或empty()时调用

<?phpclass Person{  public $sex;  private $name;  private $age;  public function __construct($name="", $age=25, $sex='男')  {    $this->name = $name;    $this->age = $age;    $this->sex = $sex;  }  /**   * @param $content   *   * @return bool   */  public function __isset($content) {    echo "当在类外部使用isset()函数测定私有成员{$content}时,自动调用<br>";    echo isset($this->$content);  }}$person = new Person("小明", 25); // 初始赋值echo isset($person->sex),"<br>";echo isset($person->name),"<br>";echo isset($person->age),"<br>";// 输出结果// 1// 1// 1

10. __unset(),当对不可访问属性调用unset()时被调用

<?phpclass Person{  public $sex;  private $name;  private $age;  /**   * @param $content   */  public function __unset($content) {    echo "当在类外部使用unset()函数来删除私有成员时自动调用的<br>";    echo unset($this->$content);  }}$person = new Person();unset($person->sex);unset($person->name);unset($person->age);

11. __sleep(),执行serialize()时,先会调用这个函数

serialize() 函数会检查类中是否存在一个魔术方法 __sleep()。如果存在,则该方法会优先被调用,然后才执行序列化操作。此功能可以用于清理对象,并返回一个包含对象中所有应被序列化的变量名称的数组。如果该方法未返回任何内容,则 NULL 被序列化,并产生一个 E_NOTICE 级别的错误。**注意:**__sleep() 不能返回父类的私有成员的名字。这样做会产生一个 E_NOTICE 级别的错误。可以用 Serializable 接口来替代。作用:__sleep() 方法常用于提交未提交的数据,或类似的清理操作。同时,如果有一些很大的对象,但不需要全部保存,这个功能就很好用。
<?phpclass Person{  public $sex;  public $name;  public $age;  public function __construct($name="", $age=25, $sex='男')  {    $this->name = $name;    $this->age = $age;    $this->sex = $sex;  }  /**   * @return array   */  public function __sleep() {    echo "当在类外部使用serialize()时会调用这里的__sleep()方法<br>";    $this->name = base64_encode($this->name);    return array('name', 'age'); // 这里必须返回一个数值,里边的元素表示返回的属性名称  }}$person = new Person('小明'); // 初始赋值echo serialize($person);echo '<br/>';// 代码运行结果:// 当在类外部使用serialize()时会调用这里的__sleep()方法// O:6:"Person":2:{s:4:"name";s:8:"5bCP5piO";s:3:"age";i:25;}

11. __debugInfo(),打印所需调试信息数

**注意**:该方法在PHP 5.6.0及其以上版本才可以用,如果你发现使用无效或者报错,请查看你的版本
<?phpclass C {  private $prop;  public function __construct($val) {    $this->prop = $val;  }  /**   * @return array   */  public function __debugInfo() {    return [      'propSquared' => $this->prop ** 2,    ];  }}var_dump(new C(42));
结果:object(C)#1 (1) { ["propSquared"]=> int(1764) }再次注意:这里的 `**` 是乘方的意思,也是在PHP5.6.0及其以上才可以使用,详情请查看PHP手册
原创粉丝点击