程序员人生 网站导航

php的魔术方法

栏目:php教程时间:2016-10-04 11:40:04

前言

  Php可以说是1个面向对象的语言,php的类中有自己独有的1些方法,不同于别的编程语言,php在定义类中除我们自己定义的属性方法之外,Php还有1写魔术方法,当我们把这些方法写出来后,我们其实不需要自己去调用。系统就会在触发某些条件以后自动调用。

  注意,当我们没有写这些魔术方法时,系统不会去调用这些魔术方法。

php提供的魔术方法有很多,这里我们只介绍经常使用的几个。

  1. __get读取不可访问或不存在的属性的值时,__get() 会被调用。

  2. __set在给不可访问或不存在的属性赋值时,__set() 会被调用。

  3. __isset() 当对不可访问或不存在属性调用 isset() 或 empty() 时,__isset() 会被调用。

  4. __unset();当对不可访问或不存在的属性调用 unset() 时,__unset() 会被调用。

  5. __call()在对象中调用1个不可访问或不存在的方法时,__call() 会被调用。

  6. __clone()可以避免他人克隆我们的对象。

  7. __tostring();方法用于1个类被当做字符串时应怎样回应。例如 echo $obj; 应当显示些甚么。
  8. __construct();PHP 5 允行开发者在1个类中定义1个方法作为构造函数。具有构造函数的类会在每次创建新对象时先调用此方法。
  9. __destruct();PHP 5 引入了析构函数的概念,析构函数会在到某个对象的所有援用都被删除或当对象被显式烧毁时履行。

  你会发现这些魔术方法的前面都有两个下划线__这是由于PHP 将所有以\ __(两个下划线)开头的类方法保存为魔术方法。所以在定义类方法时,除上述魔术方法,建议不要以\ __ 为前缀。

下面我们单个的介绍每一个魔术方法是怎样使用的。

魔术方法

__get()和__set()

  __get():读取不可访问或不存在的属性的值时,__get() 会被调用。

  __set():在给不可访问或不存在的属性赋值时,__set() 会被调用。

  在类中当属性的修饰符是protected和private的时候,在类的外部不能通过对象名的情势进行访问,如果强行读取不可访问的属性,并且你在类的内部写了__get函数,这时候候系统就会自动的调用__get魔术方法,当你强行修改不可访问属性值得时候,__set魔术方法就会被履行。

示例:

<?php
class Cat{
    protected $name;
    protected $age;
    protected $sex;

    public function __construct($name,$age,$sex){
        $this -> name = $name;
        $this -> age = $age;
        $this -> sex = $sex;
    }
    //__set方法,可以处理你自己的逻辑
    public function __set($name,$value){
        echo 'set方法被履行了<br>';
        //这里使用这个函数判断当前类中有无这个属性,避免属性出现null的情况。
        if(property_exists($this, $name)){
            $this -> $name = $value;
        }else{
            echo '你要设置的属性不存在';
        }
    }
    //__get方法,可以处理你自己的逻辑
    public function __get($name){
        echo 'get方法被履行了<br>';
        if(isset($this->$name)){
            return $this -> $name;
        }else{
            echo '你要的属性不存在,或属性值为空';
        }
    }
}
$cat = new Cat('小花',2,'雌');
echo $cat -> name . '<br>'; //读取不可访问的属性值得时候,get方法被履行
$cat -> age = 5; //修改不可访问的属性值set方法被履行
echo $cat -> age;

执行结果

property_exists()函数:检查对象或类是不是具有该属性

__isset()和__unset()

  __isset():当对不可访问或不存在属性调用isset() 或 empty() 时,__isset() 会被调用。

  __unset():当对不可访问或不存在的属性调用 unset() 时,__unset() 会被调用。

  在类的外部对对象的不能访问属性使用isset函数或empty函数的时候或这个属性在类中都没有定义。魔术方法__isset()就会履行,而进行unset操作是__unset就会自动调用。

示例:

<?php
class Cat{
    protected $name;
    protected $age;
    protected $sex;

    public function __construct($name,$age,$sex){
        $this -> name = $name;
        $this -> age = $age;
        $this -> sex = $sex;
    }
    //__isset方法,在类中可以对类的属性进行判断,并返回。
    public function __isset($name){
        echo 'isset方法履行了<br>';
        return isset($this -> $name);
    }
    //__unset方法
    public function __unset($name){
        echo 'unset方法履行了<br>';
        if(property_exists($this,$name)){
            unset($this -> $name);
        }else{
            echo '你要烧毁的属性不存在';
        }
    }
}
$cat = new Cat('小花',2,'雌');
echo isset($cat -> name);
unset($cat->age);
echo '<pre>';
var_dump($cat);

这里写图片描述

__call()

  __isset():在对象中调用1个不可访问或不存在的方法时,__call() 会被调用。

  由于php语言不支持函数的重载,可使用这个魔术方法进行重载。

示例:

<?php

class Math{

    private function add($a,$b){
        return $a + $b;
    }
    private function add1($a,$b,$c){
        return $a + $b + $c;
    }

    //这个魔术方法中有两个参数,第1个参数是传过来的函数名,第2个参数是传过来的方法中的参数组成的数组。
    public function __call($method,$arr_value){
        if($method == 'add'){
            //得到数组的数量,肯定使用那个方法。
            $total = count($arr_value);
            if($total == 2){
                return $this -> add($arr_value[0],$arr_value[1]);
            }else if($total == 3){
                return $this -> add1($arr_value[0],$arr_value[1],$arr_value[2]);
            }
        }
    }

}

$math = new Math();

echo $math -> add(1,2) . '<br>';//私有的方法,没有权限,会调用call方法.
echo $math -> add(1,2,3);

这里写图片描述

在php中同1类中1定不能有方法名相同的函数。不然后报错。

__clone()

  __clone():可以避免他人克隆我们的对象。

  php语言中有1种机制叫做克隆,如果定义了 __clone()方法,则新创建的对象(复制生成的对象)中的 __clone()方法会被调用。
程序员可以通过克隆把对象进行整体的克隆,但是有时我们不希望他人克隆我们的对象,比如单列模式,这时候使用克隆可以解决。

示例:

<?php

class Cat{
    public $name;
    public $age;

    public function __construct($name,$age){
        $this -> name = $name;
        $this -> age = $age;
    }

    public function showInfo(){
        echo '姓名是:' . $name . ' ' . '年龄是:' . $age; 
    }

    private function __clone(){

    }

}
$cat = new Cat('小花',2);
echo '<pre>';
var_dump($cat);
$cat2 = clone $cat;
var_dump($cat2);

这里写图片描述

  注意在这里魔术方法的权限修饰符是private,私有的。

__tostring()

  __tostring方法用于1个类被当做字符串时应怎样回应。例如 echo $obj;

  当我们尝试把1个对象当做字符换进行echo输出的时候,类的tostring方法就会默许被调用,在这个方法中我们可以定义对象应当输出甚么。

示例:

<?php
class Dog{
    private $name;
    private $age;
    private $color;

    public function __construct($name,$age,$color){
        $this -> name = $name;
        $this -> age = $age;
        $this -> color = $color;
    }

    //定义tostring方法
    public function __toString(){
        return  '名字是:' . $this ->name . ' ' . '年龄是:' . $this -> age . ' ' . '色彩是:' . $this ->color;
    }
}
$dog = new Dog('小白',4,'red');
echo $dog;

这里写图片描述

  注意:在tostring中必须要有1个返回值。

__construct()

  __construct():PHP 5 允行开发者在1个类中定义1个方法作为构造函数。具有构造函数的类会在每次创建新对象时先调用此方法。

  在类中定义构造函数1般是完成创建对象时,对象的初始化。当我们没有定义构造方法的时候,系统会调用他自己默许的构造函数,这个构造函数是1个无参的构造函数。

示例

<?php

class Cat{
protected $name;
protected $age;
protected $sex;

//定义1个构造函数,完成对属性的初始化。
    public function __construct($name,$age,$sex){
        $this -> name = $name;
        $this -> age = $age;
        $this -> sex = $sex;
    }
}

$cat = new Cat('小白',12,'雄');
echo '<pre>';
var_dump($cat);

这里写图片描述

__destruct()

  __destruct();PHP 5 引入了析构函数的概念,析构函数会在到某个对象的所有援用都被删除或当对象被显式烧毁时履行。

  析构函数会在函数烧毁前履行,在这里面我们可以对用到的资源进行释放,比如数据库

示例

<?php class DaoMysql{ protected $link; public function __construct($host,$user,$pwd){ $this -> link = @mysql_connect($host,$user,$pwd); } public function getLink(){ return $this -> link; } //析构函数,用来释放数据库资源。 public function __destruct(){ mysql_close($this->link); } } $daoMysql = new DaoMysql('localhost','root','123456'); $sql = 'select * from tb1'; mysql_select_db('test'); mysql_query('set names utf8'); //通过对象的到里面的链接对象。 $res = mysql_query($sql,$daoMysql -> getLink()); echo '<pre>'; while($row = mysql_fetch_assoc($res)){ var_dump($row); } //当类中没有析构函数的时候,把对象置为空,下面的获得数据还能履行, //当类中有析构函数的时候,把对象置为空,下面的获得数据会出错。说明成功的在析构方法中把数据库连接释放掉了。 $daoMysql = null; $res = mysql_query($sql); echo '<pre>'; while($row = mysql_fetch_assoc($res)){ var_dump($row); }

这里写图片描述

总结

在php中,这些魔术方法大多数都是我们操作不可操作的数据时,系统触发履行。区分于别的语言,也能够说是php的1大特点。(- _ -);

------分隔线----------------------------
------分隔线----------------------------

最新技术推荐