三、魔术方法
魔术方法其实是 PHP 为开发者提供了一种规避因为对类的私有属性操作,对不存在的方法调用等类似原因而导致的错误.下面就对 PHP 的魔术方法做简单介绍.
__set
__get
__isset
__unset
__call
__callStatic
__invoke
__set()
和 __get()
魔术方法
1. 作用: 对类的私有属性赋值或读取而不产生错误的方法.
之前我们说过, private 修饰的类的属性是私有的,不能被外部赋值也不能被取值, 但 PHP 也提供了一套魔术方法 __set()
和 __get()
, 如果在类中定义了 __set()
方法,当为私有属性赋值时,就会调用此方法, 类似的 __get()
方法,当有私有属性被读取时,就会调用此方法.
另外,值得注意的是,这两个魔术方法可以为类的实例动态设置新的属性值,不过不是很推荐这样使用,没有在类中定义的属性业务中被创建并使用会导致代码难以维护.
class Vehicle
{
private $creator = '未知';
// __set() 魔术方法
public function __set($name, $value)
{
$this->$name = $value;
}
// __get() 魔术方法
public function __get($name)
{
return $this->$name;
}
}
$vehicle = new Vehicle();
// 为私有属性赋值
$vehicle->creator = 'zZ爱吃菜';
// 读取私有属性
var_dump($vehicle->creator);
// 动态绑定新属性并赋值
$vehicle->creator2 = 'zZ爱吃菜2';
// 读取新属性
var_dump($vehicle->creator2);
// 输出结果:
string(11) "zZ爱吃菜"
string(12) "zZ爱吃菜2"
__isset()
方法
2. 作用: 判断类的私有属性是否存在,而不产生错误
在 PHP 类中定义的私有属性, 通过 isset 是不能进行判断是否的, 如果在类中定义了 __isset()
方法,当为私有属性赋值时,就会调用此方法
class Vehicle
{
private $creator = '未知';
}
$vehicle = new Vehicle();
var_dump(isset($vehicle->creator));
// 输出结果: bool(false)
如果定义了 __isset()
魔术方法,结果如下:
class Vehicle
{
private $creator = '未知';
public function __isset($name)
{
return isset($this->$name);
}
}
$vehicle = new Vehicle();
var_dump(isset($vehicle->creator));
// 输出结果: bool(true)
__unset()
方法
3. 作用: 对类的私有属性进行销毁操作(unset
), 而不产生错误
同理, 当删除一个类的私有属性是,如果定义了 __unset()
方法,就会调用此方法.
我们知道,私有属性是不能够被 unset
的. 代码如下:
class Vehicle
{
private $creator = '未知';
}
$vehicle = new Vehicle();
unset($vehicle->creator);
// 输出结果:
PHP Fatal error: Uncaught Error: Cannot access private property Vehicle::$creator
但是,当我们定义了 __unset()
魔术方法时,就可以对私有属性进行 unset 了
class Vehicle
{
private $creator = '未知';
public function __unset($name)
{
echo '删除 creator 私有属性';
unset($this->creator);
}
}
$vehicle = new Vehicle();
unset($vehicle->creator);
// 输出结果:
删除 creator 私有属性
__call()
魔术方法
4. 作用: 避免调用类的方法不存在, 而尝试错误.
当调用的类的方法不存在时, 如果类定义了 __call()
魔术方法,就会调用此方法.
如果我们调用一个类不存在的方法会有如下错误:
class Vehicle
{}
$vehicle = new Vehicle();
$vehicle->run(100, 'guangzhou');
// 输出结果:
PHP Fatal error: Uncaught Error: Call to undefined method Vehicle::run()
如果我们定义了 __call
class Vehicle
{
public function __call($name, $arguments)
{
var_dump($name, $arguments);
}
}
$vehicle = new Vehicle();
$vehicle->run(100, 'guangzhou');
// 输出结果: 会在这里打印调用的方法名,以及属性
string(3) "run"
array(2) {
[0]=>
int(100)
[1]=>
string(9) "guangzhou"
}
__callStatic
方法
5. 作用: 避免调用类的静态方法不存在, 而尝试错误.
与 __call
类似,只不过针对的是 类 的静态方法, 另外 __callStatic
也必须是静态方法 代码如下:
class Vehicle
{
public static function __callStatic($name, $arguments)
{
var_dump($name, $arguments);
}
}
// 调用不存在的静态方法
Vehicle::run(100, 'guangzhou');
// 输出结果:
string(3) "run"
array(2) {
[0]=>
int(100)
[1]=>
string(9) "guangzhou"
}
__invoke
方法
6. 作用: 避免将类的实例当做函数调用而产生错误
代码如下:
class Vehicle
{
public function __invoke($arguments)
{
var_dump($arguments);
}
}
$vehicle = new Vehicle();
$vehicle('我不是函数');
// 输出结果:
string(15) "我不是函数"
__toString
方法
7. 作用: 避免将类的实例作为字符串打印时发生错误
比较简单,我们直接看代码:
class Vehicle
{
public function __toString()
{
return '我是 Vehicle 字符串打印结果';
}
}
$vehicle = new Vehicle();
echo $vehicle;
__toString
魔术方法是比较常用的, 比如我们需要对一类字符串便描述时,可调用此方法进行返回描述.
← 二、面向对象主要特征 四、对象复制 →