PHP的重载使用魔术方法代码实例详解


Posted in PHP onFebruary 26, 2021

摘录PHP官网对PHP重载的解释:

PHP所提供的"重载"(overloading)是指动态地"创建"类属性和方法。我们是通过魔术方法(magic methods)来实现的。
当调用当前环境下未定义或不可见的类属性或方法时,重载方法会被调用。本节后面将使用"不可访问属性(inaccessible properties)"和"不可访问方法(inaccessible methods)"来称呼这些未定义或不可见的类属性或方法。
所有的重载方法都必须被声明为 public。

Note:
这些魔术方法的参数都不能通过引用传递。

Note:
PHP中的"重载"与其它绝大多数面向对象语言不同。传统的"重载"是用于提供多个同名的类方法,但各方法的参数类型和个数不同。

属性重载

public __set ( string $name , mixed $value ) : void
public __get ( string $name ) : mixed
public __isset ( string $name ) : bool
public __unset ( string $name ) : void

在给不可访问属性赋值时,__set() 会被调用。
读取不可访问属性的值时,__get() 会被调用。
当对不可访问属性调用 isset() 或 empty() 时,__isset() 会被调用。
当对不可访问属性调用 unset() 时,__unset() 会被调用。
参数 $name 是指要操作的变量名称。__set() 方法的 $value 参数指定了 $name 变量的值。
属性重载只能在对象中进行。在静态方法中,这些魔术方法将不会被调用。所以这些方法都不能被 声明为 static。

Note:
因为 PHP 处理赋值运算的方式,__set() 的返回值将被忽略。类似的, 在下面这样的链式赋值中,__get() 不会被调用:
$a = $obj->b = 8;

Note:
在除 isset() 外的其它语言结构中无法使用重载的属性,这意味着当对一个重载的属性使用 empty() 时,重载魔术方法将不会被调用。
为避开此限制,必须将重载属性赋值到本地变量再使用 empty()。

Example #1 使用 __get(),__set(),__isset() 和 __unset() 进行属性重载

class PropertyTest
{
 /** 被重载的数据保存在此 */
 private $data = array();

 /** 重载不能被用在已经定义的属性 */
 public $declared = 1;

 /** 只有从类外部访问这个属性时,重载才会发生 */
 private $hidden = 2;

 public function __set ($name, $value)
 {
 $this->data[$name] = $value;
 }

 public function __get ($name)
 {
 if (isset($this->$name)) {
 return $this->$name;
 }
 if (array_key_exists($name, $this->data)) {
 return $this->data[$name];
 }
 //产生一条回溯跟踪
 $trace = debug_backtrace();
 //抛出异常
 trigger_error('Undefined property via __get(): ' . $name . ' in ' . $trace[0]['file'] . ' on line ' . $trace[0]['line'], E_USER_NOTICE);
 return null;
 }

 public function __isset ($name)
 {
 return isset($this->data[$name]);
 }

 public function __unset ($name)
 {
 unset($this->data[$name]);
 }

 /** 非魔术方法 */
 public function getHidden ()
 {
 return $this->hidden;
 }
}

$obj = new PropertyTest;

//输出不存在的a变量,走到__get()中,会抛出异常
echo $obj->a;

//对不存在的a变量赋值为1,会走到__set()中
$obj->a = 1;

//再次输出a变量,由于上面已经对其__set(),所以这是可以访问到a的值为1
echo $obj->a;

//此时使用isset()对不存在的a变量进行运算时,会走到__isset()中,由于上面已经对其__set(),所以是true
var_dump(isset($obj->a));

//对a进行unset()时,会走到__unset()中
unset($obj->a);

//再对其进行isset(),此时已经不存在了
var_dump(isset($obj->a));

//访问private 属性的变量,会进入__get()中
echo $obj->hidden;

方法重载

public __call ( string $name , array $arguments ) : mixed
public static __callStatic ( string $name , array $arguments ) : mixed

在对象中调用一个不可访问方法时,__call() 会被调用。
在静态上下文中调用一个不可访问方法时,__callStatic() 会被调用。
$name 参数是要调用的方法名称。
$arguments 参数是一个枚举数组,包含着要传递给方法 $name 的参数。

Example #2 使用 __call() 和 __callStatic() 对方法重载

class MethodTest
{
 /**
 * 调用不存在的方法时进入此处
 * @param $name
 * @param $arguments
 */
 public function __call ($name, $arguments)
 {
 // 注意: $name 的值区分大小写
 $info = [
 'name' => $name,
 'arguments' => $arguments,
 ];
 print_r($info);
 }

 /**
 * PHP 5.3.0之后版本
 * 调用不存在的静态方法时,进入此处
 */
 public static function __callStatic ($name, $arguments)
 {
 // 注意: $name 的值区分大小写
 $info = [
 'name' => $name,
 'arguments' => $arguments,
 ];
 print_r($info);
 }
}

$arguments = ['A', 'B', 'C'];

$obj = new MethodTest;
$obj->test(...$arguments);

MethodTest::test(...$arguments); // PHP 5.3.0之后版本

/*
 * 以上两个都输出:
 * Array
 (
 [name] => test
 [arguments] => Array
 (
 [0] => A
 [1] => B
 [2] => C
 )

 )
 */

到此这篇关于PHP的重载使用魔术方法代码实例详解的文章就介绍到这了,更多相关PHP的重载使用魔术方法内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

PHP 相关文章推荐
PHP var_dump遍历对象属性的函数与应用代码
Jun 04 PHP
php连接mssql的一些相关经验及注意事项
Feb 05 PHP
深入密码加salt原理的分析
Jun 06 PHP
PHP整数取余返回负数的相关解决方法
May 15 PHP
Yii查询生成器(Query Builder)用法实例教程
Sep 04 PHP
跟我学Laravel之快速入门
Oct 15 PHP
如何使用php等比例缩放图片
Oct 12 PHP
PHP实现登录搜狐广告获取广告联盟数据的方法【附demo源码】
Oct 14 PHP
基于thinkPHP框架实现留言板的方法
Oct 17 PHP
php常用数组array函数实例总结【赋值,拆分,合并,计算,添加,删除,查询,判断,排序】
Dec 07 PHP
php安全配置记录和常见错误梳理(总结)
Mar 28 PHP
PhpStorm配置Xdebug调试的方法步骤
Feb 02 PHP
PHP解密支付宝小程序的加密数据、手机号的示例代码
Feb 26 #PHP
php中get_object_vars()在数组的实例用法
Feb 22 #PHP
MacOS下PHP7.1升级到PHP7.4.15的方法
Feb 22 #PHP
关于PhpStorm设置点击编辑文件自动定位源文件的实现方式
Dec 30 #PHP
Thinkphp5+Redis实现商品秒杀代码实例讲解
Dec 29 #PHP
PHP序列化和反序列化深度剖析实例讲解
Dec 29 #PHP
PHP实现简单注册登录系统
Dec 28 #PHP
You might like
php小型企业库存管理系统的设计与实现代码
2011/05/16 PHP
PHP小技巧之JS和CSS优化工具Minify的使用方法
2014/05/19 PHP
PHP在网页中动态生成PDF文件详细教程
2014/07/05 PHP
如何在旧的PHP系统中使用PHP 5.3之后的库
2015/12/02 PHP
PHP使用mysql与mysqli连接Mysql数据库用法示例
2016/07/07 PHP
PHP+jquery+CSS制作头像登录窗(仿QQ登陆)
2016/10/20 PHP
php变量与JS变量实现不通过跳转直接交互的方法
2017/08/25 PHP
将string解析为json的几种方式小结
2010/11/11 Javascript
找出字符串中出现次数最多的字母和出现次数精简版
2012/11/07 Javascript
jquery动态增加删除表格行的小例子
2013/11/14 Javascript
基于Jquery实现键盘按键监听
2014/05/11 Javascript
js实现C#的StringBuilder效果完整实例
2015/12/22 Javascript
JS实现支持Ajax验证的表单插件
2016/03/24 Javascript
AngularJS轻松实现双击排序的功能
2016/08/30 Javascript
easyui combobox开启搜索自动完成功能的实例代码
2016/11/08 Javascript
[01:26]神话结束了,却也刚刚开始——DOTA2新英雄玛尔斯驾临战场
2019/03/10 DOTA
[49:43]VG vs FNATIC 2019国际邀请赛小组赛 BO2 第一场 8.15
2019/08/17 DOTA
Python函数式编程指南(四):生成器详解
2015/06/24 Python
Python实时获取cmd的输出
2015/12/13 Python
举例讲解Python面向对象编程中类的继承
2016/06/17 Python
Python中对象的引用与复制代码示例
2017/12/04 Python
读取本地json文件,解析json(实例讲解)
2017/12/06 Python
python dataframe向下向上填充,fillna和ffill的方法
2018/11/28 Python
python之验证码生成(gvcode与captcha)
2019/01/02 Python
python 字典 setdefault()和get()方法比较详解
2019/08/07 Python
python selenium循环登陆网站的实现
2019/11/04 Python
Python中Subprocess的不同函数解析
2019/12/10 Python
PyCharm下载和安装详细步骤
2019/12/17 Python
CSS3简单实现照片墙
2014/12/12 HTML / CSS
css3 transform 3d 使用css3创建动态3d立方体(html5实践)
2013/01/06 HTML / CSS
学生会主席就职演讲稿
2014/01/14 职场文书
十佳美德少年事迹材料
2014/02/05 职场文书
安全生产活动月方案
2014/03/09 职场文书
中学生的1000字检讨书
2014/10/11 职场文书
公司离职证明范本
2014/10/17 职场文书
质监局领导班子践行群众路线整改方案
2014/10/26 职场文书