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 相关文章推荐
php4的session功能评述(一)
Oct 09 PHP
fleaphp crud操作之find函数的使用方法
Apr 23 PHP
php中使用Curl、socket、file_get_contents三种方法POST提交数据
Aug 12 PHP
CI框架源码阅读,系统常量文件constants.php的配置
Feb 28 PHP
基于curl数据采集之正则处理函数get_matches的使用
Apr 28 PHP
php读取mysql中文数据出现乱码的解决方法
Aug 16 PHP
有关于PHP中常见数据类型的汇总分享
Jan 06 PHP
ThinkPHP 404页面的设置方法
Jan 14 PHP
php生成PDF格式文件并且加密
Jun 22 PHP
PHP实现的贪婪算法实例
Oct 17 PHP
PHP信号处理机制的操作代码讲解
Apr 19 PHP
laravel框架语言包拓展实现方法分析
Nov 22 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 阴历-农历-转换类代码
2012/01/16 PHP
php preg_filter执行一个正则表达式搜索和替换
2012/02/27 PHP
解析mysql 表中的碎片产生原因以及清理
2013/06/22 PHP
CodeIgniter中使用Smarty3基本配置
2015/06/29 PHP
PHP中的switch语句的用法实例详解
2015/10/21 PHP
自制PHP框架之模型与数据库
2017/05/07 PHP
JavaScript中的noscript元素属性位置及作用介绍
2013/04/11 Javascript
jquery ajax的success回调函数中实现按钮置灰倒计时
2013/11/19 Javascript
纯css+js写的一个简单的tab标签页带样式
2014/01/28 Javascript
一个CSS+jQuery实现的放大缩小动画效果
2014/02/19 Javascript
js数组常见操作及数组与字符串相互转化实例详解
2015/11/10 Javascript
浅谈Angularjs link和compile的使用区别
2016/10/21 Javascript
bootstrap组件之按钮式下拉菜单小结
2017/01/19 Javascript
express框架实现基于Websocket建立的简易聊天室
2017/08/10 Javascript
node.js 基于cheerio的爬虫工具的实现(需要登录权限的爬虫工具)
2019/04/10 Javascript
vue路由守卫+登录态管理实例分析
2019/05/21 Javascript
VueCli3.0中集成MockApi的方法示例
2019/07/05 Javascript
vue-devtools的安装和使用步骤详解
2019/10/17 Javascript
深入了解JavaScript词法作用域
2020/07/29 Javascript
修复CentOS7升级Python到3.6版本后yum不能正确使用的解决方法
2018/01/26 Python
Python3实现取图片中特定的像素替换指定的颜色示例
2019/01/24 Python
对Python3中dict.keys()转换成list类型的方法详解
2019/02/03 Python
Python使用ffmpy将amr格式的音频转化为mp3格式的例子
2019/08/08 Python
YUV转为jpg图像的实现
2019/12/09 Python
windows10 pycharm下安装pyltp库和加载模型实现语义角色标注的示例代码
2020/05/07 Python
python高级特性简介
2020/08/13 Python
Python paramiko使用方法代码汇总
2020/11/20 Python
Pharmacy Online中文直邮网站:澳洲大型药房
2020/06/27 全球购物
药学专业个人自我评价
2013/11/11 职场文书
库房主管岗位职责
2013/12/31 职场文书
中秋节主持词
2014/04/02 职场文书
2014大学辅导员工作总结
2014/12/02 职场文书
求职自我评价怎么写
2015/03/09 职场文书
婚姻出轨保证书
2015/05/08 职场文书
神州牡丹园的导游词
2019/11/20 职场文书
python 自动刷新网页的两种方法
2021/04/20 Python