魔术方法的触发条件

魔术方法参数触发条件返回值
__construct()称为构造函数,在实例化一个对象的时候,首先会自动执行这个方法
__destruct()称为析构函数,在对象的所有引用被删除或者当对象被显示销毁时执行的魔术方法,反序列化时也是对象,所有最后也会被销毁触发
__sleep() 在serialize()序列化之前
__wakeup()反序列化unserialize()之前
__toString()把对象当成字符串来调用,例如echo,die则会触发,而printf_r和var_dump不会触发
__invoke()把对象当成函数来调用会触发
__call()$arg1,$arg2调用一个不存在的方法时会触发,$agr1不存在方法的名称,$arg2不存在方法的参数调用的不存在方法的名称和参数
__callStatic()$arg1,$arg2静态调用或调用成员常量时使用的方法不存在时触发调用的不存在方法的名称和参数
__get()$arg1调用的成员属性不存在时触发不存在的成员属性的名称
__set()$arg1,$arg2给不存在的成员属性赋值时触发不存在的成员属性的名称和赋的值
__isset()$arg1对不可访问属性使用isset()empty()时,isset()会被触发不存在的成员属性的名称
__unset()$arg1对不可访问属性使用unset()时会触发不存在的成员属性和名称
__cloe()当使用clone关键词拷贝完成一个对象后,新对象会自动调用定义的魔术方法__clone()

魔术方法的使用案例

__construct()

触发条件:在实例化一个对象的时候,首先会自动执行这个方法

<?php
highlight_file(__FILE__);
class User {
    public $username;
    public function __construct($username) {
        $this->username = $username;
        echo "触发了构造函数1次" ;
    }
}
$test = new User("benben");
$ser = serialize($test);
unserialize($ser);
?>

真正运行触发__construct魔术方法的是$test = new User("benben");

运行结果:触发了构造函数1次

__destruct()

触发条件:在对象的所有引用被删除或者当对象被显示销毁时执行的魔术方法,反序列化时是将字符串转换成对象的过程,所有最后也会被销毁触发

<?php
highlight_file(__FILE__);
class User {
    public function __destruct()
    {
        echo "触发了析构函数1次"."<br />" ;
    }
}
$test = new User("benben");
$ser = serialize($test);
unserialize($ser);

?>

触发了两次__destruct()魔术方法,也就是说在new一个对象最终被销毁会触发一次,然后unserialize反序列化成对象的过程,最终销毁也触发了一次

运行结果:

触发了析构函数1次
触发了析构函数1次

__sleep()

触发条件:在serialize()序列化之前

<?php
highlight_file(__FILE__);
class User {
    const SITE = 'uusama';
    public $username;
    public $nickname;
    private $password;
    public function __construct($username, $nickname, $password)    {
        $this->username = $username;
        $this->nickname = $nickname;
        $this->password = $password;
    }
    public function __sleep() {
        return array('username', 'nickname');
    }
}
$user = new User('a', 'b', 'c');
echo serialize($user);
?>

new一个对象先触发__construct(),然后serialize()触发了__sleep(),最后返回一个数组给$uer,内容只有username和nickname;

结果:O:4:"User":2:{s:8:"username";s:1:"a";s:8:"nickname";s:1:"b";}

__wakeup()

触发条件:在unserialize()反序列化之前[/font]

<?php
highlight_file(__FILE__);
error_reporting(0);
class User {
    const SITE = 'uusama';
    public $username;
    public $nickname;
    private $password;
    private $order;
    public function __wakeup() {
        $this->password = $this->username;
    }
}
$user_ser = 'O:4:"User":2:{s:8:"username";s:1:"a";s:8:"nickname";s:1:"b";}';
var_dump(unserialize($user_ser));
?>

unserialize()触发了__wakeup(),因此username的值赋给了password

结果:object(User)#1 (4) { ["username"]=> string(1) "a" ["nickname"]=> string(1) "b" ["password":"User":private]=> string(1) "a" ["order":"User":private]=> NULL }

__toString()

触发条件:把对象当成字符串来调用,例如echo,die则会触发,而printf_r和var_dump不会触发

<?php
highlight_file(__FILE__);
error_reporting(0);
class User {
    var $benben = "this is test!!";
         public function __toString()
         {
             return '格式不对,输出不了!';
          }
}
$test = new User() ;
print_r($test);
echo "<br />";
echo $test;
?>

echo $test则把对象当做字符串输出了,因此调用了__toString()方法,

当使用die($test)也会触发这个魔术方法

结果:

User Object ( [benben] => this is test!! )
格式不对,输出不了!

__invoke()

触发条件:把对象当成函数来调用会触发

<?php
highlight_file(__FILE__);
error_reporting(0);
class User {
    var $benben = "this is test!!";
         public function __invoke()
         {
             echo  '它不是个函数!';
          }
}
$test = new User() ;
echo $test ->benben;
echo "<br />";
echo $test() ->benben;
?>

$test这个对象当做函数运行了,则会执行 __invoke()

结果:this is test!! 它不是个函数!

__call()

触发条件:调用一个不存在的方法时会触发,$agr1不存在方法的名称,$arg2不存在方法的参数

返回值:调用的不存在方法的名称和参数

<?php
highlight_file(__FILE__);
error_reporting(0);
class User {
    public function __call($arg1,$arg2)
    {
        echo "$arg1,$arg2[0]";
          }
}
$test = new User() ;
$test -> callxxx('a');
?>

callxxx()这个方法不存在,则会调用魔术方法__call(),返回了callxxx,a

结果:callxxx,a

__callStatic()

触发条件:静态调用或调用成员常量时使用的方法不存在时触发

返回值:调用的不存在方法的名称和参数

<?php
highlight_file(__FILE__);
error_reporting(0);
class User {
    public function __callStatic($arg1,$arg2)
    {
        echo "$arg1,$arg2[0]";
          }
}
$test = new User() ;
$test::callxxx('a');
?>

$test::callxxx('a');中的::则是静态调用的方法,callxxx()方法不存在,同时在php中也会警告提醒

Warning: The magic method __callStatic() must have public visibility and be static in /var/www/html/class10/2.php on line 5

结果:callxxx,a $arg1是不存在的方法,$arg2是不存在方法中的参数

__get()

触发条件:调用的成员属性不存在时触发

返回值:不存在的成员属性的名称

<?php
highlight_file(__FILE__);
error_reporting(0);
class User {
    public $var1;
    public function __get($arg1)
    {
        echo  $arg1;
    }
}
$test = new User() ;
$test ->var2;
?>

var2成员变量不存在,则调用__get()方法,并返回不存在的成员变量名称

结果:var2

__set()

触发条件:给不存在的成员属性赋值时触发

返回值:不存在的成员属性的名称和赋的值

<?php
highlight_file(__FILE__);
error_reporting(0);
class User {
    public $var1;
    public function __set($arg1 ,$arg2)
    {
        echo  $arg1.','.$arg2;
    }
}
$test = new User() ;
$test ->var2=1;
?>

触发过程同上,返回的是var2是不存在变量名; 给不存在变量赋的值1

结果:var2,1

__isset()

触发条件:对不可访问属性使用isset()empty()时,isset()会被触发

返回值:不存在的成员属性的名称

<?php
highlight_file(__FILE__);
error_reporting(0);
class User {
    private $var;
    public function __isset($arg1 )
    {
        echo  $arg1;
    }
}
$test = new User() ;
isset($test->var);
?>

使用isset()方法对不可访问属性$var进行访问,触发了此魔术方法,并返回了var

结果:var

__unset()

触发条件:对不可访问属性使用unset()时会触发

返回值:不存在的成员属性和名称

<?php
highlight_file(__FILE__);
error_reporting(0);
class User {
    private $var;
    public function __unset($arg1 )
    {
        echo  $arg1;
    }
}
$test = new User() ;
unset($test->var);
?>

过程同上

结果:var

__clone()

触发条件:当使用clone关键词拷贝完成一个对象后,新对象会自动调用定义的魔术方法__clone()

<?php
highlight_file(__FILE__);
error_reporting(0);
class User {
    private $var;
    public function __clone( )
    {
        echo  "__clone test";
          }
}
$test = new User() ;
$newclass = clone($test)
?>

拷贝了$test这个对象,触发了__clone()

结果:__clone test

最后修改:2022 年 12 月 15 日
如果觉得我的文章对你有用,请随意赞赏