PHP魔术方法笔记
前言
在 PHP 中,以双下划线__开始命名的方法被称作 PHP 中的魔术方法,它们在 PHP 中充当很重要的角色。
常见的魔术方法有:
__construct():构造函数
__destruct():析构函数
__get(): 访问不存在的成员变量时调用
__set():设置不存在的成员变量时调用
__call():调用一个对象中不存在或被权限控制中的方法时,__call()将被调用。
__callStatic():调用一个对象中不存在或被权限控制中的静态方法时,__callStatic()将被调用。
__isset():用isset或empty检测一个对象的属性是否设置并且这个属性不存在(或被权限控制)时会自动调用__isset()方法
__unset():当调用reset()对一个未定义或不可达的成员更新时,__unset()方法将被调用
__slepp():当执行serialize()时,__slepp()方法将首先被调用。
__wakeup():当执行unserialize()方法时,__wakeup()将首先被调用。
__toString():将一个对象当作字符串来使用时__toString()方法将首先被调用。
__invoke():使用调用函数访问一个对象时,__invoke()将被调用。
__clone():当对象被复制完成时,__clone()将被调用
构造函数__construct()
当类被实例化的时候自动调用
<?php
class Test{
public function __construct()
{
echo 'izero 761202280';
}
}
$t = new Test;
// 输出:izero 761202280
析构函数:__destruct()
在对象销毁时调用
<?php
class Test{
public function __destruct()
{
echo 'izero 761202280';
}
}
$t = new Test;
unset($t); // 销毁对象
// 输出:izero 761202280
__get() 与 __set()
__get(): 访问不存在的成员变量时调用
__set():设置不存在的成员变量时调用
// __get()
<?php
class Test{
private $age;
public function __construct($age)
{
$this->age = $age;
}
public function __get($name)
{
echo '进入__get----';
if ($name == "age")
{
return 0;
}
}
}
$t = new Test(18);
echo "年龄:".$t->age;
echo $t->test; // 读取一个不存在的属性
// 输出:
进入__get----年龄:0
进入__get----
// __set()
<?php
class Test{
private $age;
public function __construct($age)
{
$this->age = $age;
}
public function __set($name, $value)
{
$this->$name = $value;
echo "进入__set:$name = $value";
}
}
$t = new Test(18);
$t->test = 'test1';
// 输出:进入__set:test = test1
__call() 与 __callStatic
__call():调用一个对象中不存在或被权限控制中的方法时,__call()将被调用。
__callStatic():调用一个对象中不存在或被权限控制中的静态方法时,__callStatic()将被调用。
<?php
header("Content-Type: text/html; charset=utf-8");
class Test1{
// $name : 名称
// $arguments : 参数
public function __call($name, $arguments)
{
echo '自动调用了__call方法:<br />';
echo "$name = $arguments<br />";
}
public static function __callStatic($name, $arguments)
{
echo '自动调用__callStatic方法:<br />';
echo "$name = $arguments<br />";
}
private function test(){
echo 'test() ';
}
}
$t = new Test1;
$t->test(123); // 调用一个私有方法
$t->test2("hello"); // 调用一个不存在的方法
$t::test3(); // 静态调用了一个不存在的方法
/*
输出:
自动调用了__call方法:
test = Array
自动调用了__call方法:
test2 = Array
自动调用__callStatic方法:
test3 = Array
*/
__isset()
用isset或empty检测一个对象的属性是否设置并且这个属性不存在(或被权限控制)时会自动调用__isset()方法
<?php
class Test1{
public function __isset($name)
{
echo "自动调用了__isset方法:$name<br />";
}
}
$t = new Test1;
isset($t->age);
isset($t->a);
empty($t->age);
empty($t->b);
/*
输出:
自动调用了__isset方法:a
自动调用了__isset方法:b
*/
__unset()
当调用reset()对一个未定义或不可达的成员更新时,__unset()方法将被调用
<?php
header("Content-Type: text/html; charset=utf-8");
class Test1{
public $age;
private $b;
public function __unset($name)
{
echo "自动调用了__unset方法:$name<br />";
}
}
$t = new Test1;
unset($t->a);
unset($t->age);
unset($t->b);
/*
输出:
自动调用了__unset方法:a
自动调用了__unset方法:b
*/
__slepp()
serialize函数会检查类中是否存在魔术方法__sleep()
。如果存在,该方法会先被调用,然后才能执行序列化操作。 此功能可以用于清理对象,并返回一个包含对象中所有应被序列化的变量名称数组,如果该方法不返回任何内容,则NULL被序列化,并产生一个E_NOTICE级别的错误。
对象被序列化之前触发,返回需要被序列化存储的成员属性,删除不必要的属性。
代码示例:
<?php
class User{
public $username;
public $password;
public function __sleep()
{
return array('username');
}
}
$user = new User();
$user->username = "admin";
$user->password = "admin";
var_dump(serialize($user));
// 输出:string(42) "O:4:"User":1:{s:8:"username";s:5:"admin";}"
// 输出的结果很显然序列化的时候忽略了 password 字段的值。
__wakeup()
unserialize会检查是否存在一个__wakeup()
方法。如果存在,则会先调用 __wakeup()
方法,预先准备对象需要的资源。 预先准备对象资源,返回void,常用于反序列化操作中重新建立数据库连接或执行其他初始化操作。
代码示例:
<?php
class User{
public $username;
public $password;
function __wakeup(): void
{
$this->password = $this->username;
}
}
var_dump(unserialize('O:4:"User":1:{s:8:"username";s:5:"admin";}'));
/*
输出
object(User)#1 (2) {
["username"]=>
string(5) "admin"
["password"]=>
string(5) "admin"
}
*/
__toString()
将一个对象当作字符串来使用时,如:字符串输出、字符串连接、相等比较、经过php字符串函数:strlen()、addslashes()等,会自动调用该方法。如echo $obj;
此方法必须返回一个字符串,否则将发出一条 E_RECOVERABLE_ERROR
级别的致命错误。
<?php
header("Content-Type: text/html; charset=utf-8");
class Test1{
public function __toString()
{
echo '自动调用了__toString()方法<br />';
return "";
}
}
$t = new Test1;
echo $t;
/*
输出:
自动调用了__toString()方法
*/
__invoke()
使用调用函数访问一个对象时,__invoke()将被调用。
<?php
header("Content-Type: text/html; charset=utf-8");
class Test1{
public function __invoke()
{
echo '自动调用了__invoke()方法<br />';
}
}
$t = new Test1;
$t();
/*
输出:
自动调用了__invoke()方法
*/
__clone()
当对象被复制完成时,__clone()将被调用
<?php
header("Content-Type: text/html; charset=utf-8");
class Test1{
public function __clone()
{
echo '__clone方法自动调用';
}
}
$t = new Test1;
$t2 = clone $t; // clone 克隆对象
/*
输出:
__clone方法自动调用
*/
本文作者:iZero
本文链接:https://www.cnblogs.com/bk76120/p/17402722.html
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步