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 破解防盗链图片函数
Dec 09 PHP
彻底杜绝PHP的session cookie错误
Aug 09 PHP
PHP 网络开发详解之远程文件包含漏洞
Apr 25 PHP
PHP操作XML作为数据库的类
Dec 19 PHP
php小技巧 把数组的键和值交换形成了新的数组,查找值取得键
Jun 02 PHP
PHP中如何定义和使用常量
Feb 28 PHP
php获取textarea的值并处理回车换行的方法
Oct 20 PHP
PHP中iconv函数转码时截断字符问题的解决方法
Jan 21 PHP
PHP加密解密字符串汇总
Apr 26 PHP
PHP比较运算符的详细介绍
Sep 29 PHP
ubutu 16.04环境下,PHP与mysql数据库,网页登录验证实例讲解
Jul 20 PHP
php文件操作之文件写入字符串、数组的方法分析
Apr 15 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 禁止页面缓存输出
2009/01/07 PHP
PHP 进程锁定问题分析研究
2009/11/24 PHP
PHP记录搜索引擎蜘蛛访问网站足迹的方法
2015/04/15 PHP
功能强大的PHP POST提交数据类
2016/07/15 PHP
JQuery的AJAX实现文件下载的小例子
2013/05/15 Javascript
js网页版计算器的简单实现
2013/07/02 Javascript
JSP跨iframe如何传递参数实现代码
2013/09/21 Javascript
js实现class样式的修改、添加及删除的方法
2015/01/20 Javascript
jQuery实现下滑菜单导航效果代码
2015/08/25 Javascript
jQuery实现鼠标经过时出现隐藏层文字链接的方法
2015/10/12 Javascript
JS+JSP通过img标签调用实现静态页面访问次数统计的方法
2015/12/14 Javascript
第一次动手实现bootstrap table分页效果
2016/09/22 Javascript
nodejs 实现钉钉ISV接入的加密解密方法
2017/01/16 NodeJs
Angualrjs 表单验证的两种方式(失去焦点验证和点击提交验证)
2017/05/09 Javascript
解决Layui数据表格中checkbox位置不居中的方法
2018/08/15 Javascript
JS实现的input选择图片本地预览功能示例
2018/08/29 Javascript
vue+高德地图实现地图搜索及点击定位操作
2020/09/09 Javascript
Python高效编程技巧
2013/01/07 Python
python使用Queue在多个子进程间交换数据的方法
2015/04/18 Python
玩转python爬虫之爬取糗事百科段子
2016/02/17 Python
Python多线程应用于自动化测试操作示例
2018/12/06 Python
pandas把所有大于0的数设置为1的方法
2019/01/26 Python
Python面向对象程序设计示例小结
2019/01/30 Python
Python将列表数据写入文件(txt, csv,excel)
2019/04/03 Python
简单了解Django应用app及分布式路由
2019/07/24 Python
Python使用turtle库绘制小猪佩奇(实例代码)
2020/01/16 Python
python下载的库包存放路径
2020/07/27 Python
Python实现Canny及Hough算法代码实例解析
2020/08/06 Python
荷兰之家英文站:Holland at Home
2016/10/26 全球购物
巴西补充剂和维生素购物网站:Natue
2019/06/17 全球购物
文史专业毕业生自荐信
2013/11/17 职场文书
电子装配专业毕业生求职信
2014/04/23 职场文书
高一课前三分钟演讲稿
2014/09/13 职场文书
2015年库房管理工作总结
2015/10/14 职场文书
JPA 通过Specification如何实现复杂查询
2021/11/23 Java/Android
win10壁纸在哪个文件夹 win10桌面背景图片文件位置分享
2022/08/05 数码科技