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 相关文章推荐
JAVA/JSP学习系列之四
Oct 09 PHP
php MYSQL 数据备份类
Jun 19 PHP
一个典型的PHP分页实例代码分享
Jul 28 PHP
php计算当前程序执行时间示例
Apr 24 PHP
php mb_substr()函数截取中文字符串应用示例
Jul 29 PHP
php中使用in_array() foreach array_search() 查找数组是否包含时的性能对比
Apr 14 PHP
PHP实现多文件上传的方法
Jul 08 PHP
php链表用法实例分析
Jul 09 PHP
ThinkPHP+EasyUI之ComboTree中的会计科目树形菜单实现方法
Jun 09 PHP
PHP7.1实现的AES与RSA加密操作示例
Jun 15 PHP
PHP数组对象与Json转换操作实例分析
Oct 22 PHP
php生成短网址/短链接原理和用法实例分析
May 29 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连接和操作MySQL数据库基础教程
2014/09/29 PHP
php实用代码片段整理
2016/11/12 PHP
js apply/call/caller/callee/bind使用方法与区别分析
2009/10/28 Javascript
JavaScript Sort 表格排序
2009/10/31 Javascript
基于jquery的监控数据是否发生改变
2011/04/11 Javascript
JavaScript模块随意拖动示例代码
2014/05/27 Javascript
js锁屏解屏通过对$.ajax进行封装实现
2014/07/31 Javascript
JavaScript检查弹出窗口是否被阻拦的方法技巧
2015/03/13 Javascript
js表单中选择框值的获取及表单的序列化
2015/12/17 Javascript
jQuery Easyui使用(一)之可折叠面板的布局手风琴菜单
2016/08/17 Javascript
vue的状态管理模式vuex
2017/11/30 Javascript
利用Vue构造器创建Form组件的通用解决方法
2018/12/03 Javascript
小程序登录之支付宝授权的实现示例
2019/12/13 Javascript
js前端传json后台接收‘‘被转为quot的问题解决
2020/11/12 Javascript
使用Node.js和Socket.IO扩展Django的实时处理功能
2015/04/20 Python
python实现的正则表达式功能入门教程【经典】
2017/06/05 Python
Python编程实现正则删除命令功能
2017/08/30 Python
Python3实现腾讯云OCR识别
2018/11/27 Python
python+mysql实现教务管理系统
2019/02/20 Python
python模块之subprocess模块级方法的使用
2019/03/26 Python
使用Python Pandas处理亿级数据的方法
2019/06/24 Python
Python调用scp向服务器上传文件示例
2019/12/22 Python
python matplotlib工具栏源码探析二之添加、删除内置工具项的案例
2021/02/25 Python
解决python的空格和tab混淆而报错的问题
2021/02/26 Python
HTML5 canvas基本绘图之绘制线条
2016/06/27 HTML / CSS
Canvas波浪花环的示例代码
2020/08/21 HTML / CSS
英文自荐信格式
2013/11/28 职场文书
大一军训感言
2014/01/09 职场文书
服务员岗位职责
2014/01/29 职场文书
税务会计岗位职责
2014/02/18 职场文书
奖学金个人总结
2015/03/04 职场文书
2015学校年度工作总结
2015/05/11 职场文书
一个独生女的故事观后感
2015/06/04 职场文书
PySwarms(Python粒子群优化工具包)的使用:GlobalBestPSO例子解析
2021/04/05 Python
SQLServer2019 数据库的基本使用之图形化界面操作的实现
2021/04/08 SQL Server
红灯733-1型14管5波段半导体收音机
2021/04/22 无线电