沉睡的木乃伊:var_export() 与可解析字符串

文章目录

  • 参考
  • 环境
  • var_export()
      • 概念
      • 应用场景
          • 数据持久化
          • 调试
      • 函数 var_export()
  • 自定义类
      • __set_state() 魔术方法
      • 设置 __set_state 魔术方法的逻辑以复原对象
      • 注意事项
  • 通用内置空类 stdClass
      • stdClass
      • 对 __set_state() 的天然支持

参考

项目描述
搜索引擎BingGoogle
AI 大模型文心一言通义千问讯飞星火认知大模型ChatGPT
PHP 官方PHP Manual
PHP 官方language.oop5.magic.php
PHP 官方function.var-export.php

环境

项目描述
PHP5.5.05.6.87.0.07.2.57.4.98.0.08.2.9
PHP 编辑器PhpStorm 2023.1.1(专业版)

var_export()

概念

var_export() 是 PHP 中用于 将数据转换为合法的 PHP 可解析字符串的一个内置函数var_export() 函数的主要目的是生成一个字符串,该字符串包含了一个 数据及该数据所属的数据类型的表示,以便后续可以通过 eval() 函数重新恢复该数据。

应用场景

数据持久化

var_export()eval() 可以用于实现数据持久化,因为它们共同提供了一种 将数据结构序列化为字符串,然后在需要时重新创建该数据结构的方法。这个过程可以用于将数据保存在文件或数据库中,然后在以后重新加载和使用它。

调试

var_export() 生成的输出易于阅读,它以有效的 PHP 代码形式表示变量的 值和类型,使开发人员能够快速理解变量的内容。

函数 var_export()

函数 var_export() 的大致定义如下:

function var_export(     mixed $value,     bool $return = false 
): null|string

其中:

属性描述
$value该参数用于指定 需要被转化为合法的 PHP 可解析字符串的变量或数据
$return该参数用于指定 是否需要将转化结果作为函数的返回值进行返回。如果为 false(默认值),则转化结果将 直接输出至终端,至于函数的返回值将被设置为 NULL

举个栗子

<?php$arr = [1, 2, 3, 4, 5];
print("数组:\n");
var_export($arr);print("\n\n字符串:\n");
var_export("Hello World");print("\n\n整型:\n");
var_export(1);print("\n\n布尔型:\n");
$result = var_export(TRUE, true);
print($result);print("\n\nPHP 提供的内置通用空类的实例化对象:\n");
var_export(new stdClass());print("\n\n自定义空类的实例化对象:\n");
class MyClass {};
var_export(new MyClass());print("\n\n资源类型:\n");
$fp = fopen('./path/to/file', 'r');
var_export($fp);

执行效果

数组:
array (0 => 1,1 => 2,2 => 3,3 => 4,4 => 5,
)字符串:
'Hello World'整型:
1布尔型:
truePHP 提供的内置通用空类的实例化对象:
(object) array(
)自定义空类的实例化对象:
MyClass::__set_state(array(
))资源类型:
NULL

自定义类

__set_state() 魔术方法

var_export() 函数在处理自定义对象时,会尝试将对象转化为形如

被处理对象所属的类::__set_state(array('属性1' => '属性值1','属性2' => '属性值2',
))

的字符串。在通过 eval() 函数复原对象时,字符串将被视为 PHP 代码进行执行,静态魔术方法 __set_state() 将被调用。属性与属性值组成的关联数组将被作为 __set_state() 方法的参数 用于规定复原对象的逻辑。若尝试通过 eval() 函数将一个未定义 __set_state() 方法的对象的可解析字符串还原为对象,则 PHP 将为此抛出 Fatal Error 异常。对此,请参考如下示例:

<?phpclass MyClass
{public $name = "RedHeart";public $age = 18;public $nation = "China";
}$indicate_text = var_export(new MyClass(), true);
print($indicate_text . "\n");# 尝试通过 eval 将可解析字符串还原为对象
$result = eval('return ' . $indicate_text . ';');
print_r($result);

在上述示例代码中,为了将 $inidicate_text 的执行结果作为 eval 函数的返回值进行返回,我们将 $indicate_textreturn 语句进行拼接,又由于 eval() 函数的参数必须为 合法的可解析的 PHP 代码,我们又在 $indicate_text 的末尾拼接了 分号

执行效果

使用 eval() 函数将 var_export() 函数产生的可解析字符串复原为原始对象需要该对象的所属类实现了 __set_state() 魔术方法。否则,PHP 将抛出 Fatal Error 异常并立即终止。

MyClass::__set_state(array('name' => 'RedHeart','age' => 18,'nation' => 'China',
))
PHP Fatal error:  Uncaught Error: Call to undefined method MyClass::__set_state() in C:\test.php(15) : eval()'d code:1
Stack trace:
#0 C:\test.php(15): eval()
#1 {main}thrown in C:\test.php(15) : eval()'d code on line 1

设置 __set_state 魔术方法的逻辑以复原对象

__set_state() 魔术方法通过 var_export() 提供的 原始对象的属性信息 将能够对原始对象进行还原。对此,请参考如下示例:

<?phpclass MyClass
{static function __set_state($obj_details) {# 将自生实例化为一个对象$obj = new self();# 循环遍历由原始对象的属性信息组成的数组foreach($obj_details as $key => $value) {# 将关联数组中的键作为对象的属性,# 值作为相应属性的属性值。$obj -> $key = $value;}# 将复原对象作为返回值进行返回return $obj;}
}$myClass = new MyClass();$myClass -> name = "RedHeart";
$myClass -> age = 19;
$myClass -> nation = "China";# 通过 var_export(?, true) 获取对象的可解析字符串并将其输出至终端
$indicate_text = var_export($myClass, true);
print($indicate_text . "\n");# 复原原始对象并将对象的结构输出至终端
$result = eval('return ' . $indicate_text . ";");
var_dump($result);

执行效果

MyClass::__set_state(array('name' => 'RedHeart','age' => 19,'nation' => 'China',
))
object(MyClass)#2 (3) {["name"]=>string(8) "RedHeart"["age"]=>int(19)["nation"]=>string(5) "China"
}

注意事项

var_export()eval() 两者的配合进行对象的数据持久化与复原的过程中,var_export() 函数并不是必须存在的,若对 var_export 函数的输出信息较为了解,则 可以自行构造所需的字符串以实现对象的数据持久化
而在 eval() 函数使用原始对象的属性信息复原对象时,需要调用所属类的 __set_state() 方法,这就意味着被复原对象的所属类必须在尝试复原对象前进行定义。
调用 __set_state() 方法复原对象与类的实例对象无关(可以在类不被实例化任何对象时进行),故需要将 __set_state() 方法设置为静态方法。否则,PHP 将抛出 Fatal Error 异常并立即停止运行。

对于 var_export() 与 eval() 两者的配合进行对象的数据持久化与复原的过程中 需要注意的事项整理如下:

  1. var_export() 函数并不是获取对象可解析字符串的 唯一方式
  2. 被复原对象的所属类必须 在尝试复原对象前进行定义
  3. __set_state() 魔术方法必须被定义为 静态方法

举个栗子

<?phpclass MyClass
{static function __set_state($obj_details) {$obj = new self();foreach($obj_details as $key => $value) {$obj -> $key = $value;}return $obj;}
}# 自定义对象的可解析字符串
$indicate_text = "MyClass::__set_state(array('name' => 'RedHeart','age' => 19,'nation' => 'China',))";$result = eval('return ' . $indicate_text . ";");
var_dump($result);

执行效果

object(MyClass)#1 (3) {["name"]=>string(8) "RedHeart"["age"]=>int(19)["nation"]=>string(5) "China"
}

通用内置空类 stdClass

stdClass

stdClass 是 PHP 提供的一个 基础类,用于创建一个 没有预定义结构的空对象(stdClass 中没有定义任何成员)stdClass 的结构大致如此:

class stdClass {}

stdClass 提供了一种方式,允许开发者 在运行时动态地创建和管理对象属性,而不必预先定义一个完整的类。对此,请参考如下示例:

<?php// stdClass 属于 PHP 的基础类,
// 是 PHP 的一部分,可以直接进行使用。
$myClass = new stdClass();// 在 PHP 运行过程中动态的对属性进行创建与管理
$myClass -> name = "RedHeart";
$myClass -> nation = "BinaryMoon";
$myClass -> nation = "China";print_r($myClass);

执行效果

stdClass Object
([name] => RedHeart[nation] => China
)

对 __set_state() 的天然支持

PHP 的内置类 stdClass 尽管是一个空类但却对 __set_state() 魔术方法存在 天然的支持(PHP 内部已为 stdClass 实例对象提供了 __set_state 实现)。对此,请参考如下示例:

<?php$myClass = new stdClass();# 获取 stdClass 实例对像的方法列表并将其输出
print_r(get_class_methods($myClass));# 定义 stdClass 实例对象的可解析字符串
$indicate_text = "(object)array('name' => 'RedHeart','age' => 19,'nation' => 'China',)";# 尝试通过 eval() 函数还原 stdClass 对象
$result = eval('return ' . $indicate_text . ';');
print_r($result);

执行效果

由上述示例代码的执行结果可知,即使 stdClass 未定义 __set_state 方法,该方法也能被成功被调用并执行还原对象的功能

Array
(
)
stdClass Object
([name] => RedHeart[age] => 19[nation] => China
)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/106785.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Vue2+SpringBoot实现数据导出到csv文件并下载

前言 该功能用于导出数据到csv文件&#xff0c;并且前端进行下载操作。涉及到java后端以及前端。后端获取数据并处理&#xff0c;前端获取返回流并进行下载操作。csv与excel文件不大相同。如果对导出的数据操作没有很高要求的话&#xff0c;csv文件就够了。具体差异自行百度。我…

BootStrap-前端框架

资料:https://v3.bootcss.com/components/ BootStrap的概念&#xff08;Web框架&#xff09; Bootstrap&#xff0c;来自 Twitter&#xff0c;是目前很受欢迎的前端框架。Bootstrap 是基于 HTML、CSS、JavaScript 的&#xff0c;它简洁灵活&#xff0c;使得 Web 开发更加快捷。…

TLS/SSL 详解

目录 基础理论入门HTTPS对称加密非对称加密证书TLS握手过程握手总结 TLS 定义(记录层/握手层)HTTPS HTTP over TLS加密记录层分片 (Fragmentation)记录压缩和解压缩 (Record compression and decompression)空或标准流加密 (Null or standard stream cipher)CBC 块加密 (分组加…

C语言编译过程

最近在看C语言的基础知识&#xff0c;之前只关注编译最后生成的二进制文件&#xff0c;不知道编译过程&#xff0c;学习到了整理一下。 一、C语言编译过程 过程如下&#xff1a; 预编译---->编译---->汇编---->链接器输出---->二进制文件。 编译器将编译分为预…

出差学知识No3:ubuntu查询文件大小|文件包大小|磁盘占用情况等

1、查询单个文件占用内存大小2、显示一个目录下所有文件和文件包的大小3、显示ubuntu所有磁盘的占用情况4、查看ubuntu单个包的占用情况 1、查询单个文件占用内存大小 使用指令&#xff1a;ls -lh 文件 2、显示一个目录下所有文件和文件包的大小 指令&#xff1a;du -sh* 3…

【特纳斯电子】基于单片机的火灾监测报警系统-实物设计

视频及资料链接&#xff1a;基于单片机的火灾监测报警系统-实物设计 - 电子校园网 (mcude.com) 编号&#xff1a; T0152203M-SW 设计简介&#xff1a; 本设计是基于单片机的火灾监测报警系统&#xff0c;主要实现以下功能&#xff1a; 1.通过OLED显示温度、烟雾、是否有火…

Linux:Termius连接本地虚拟机与虚拟机快照

Termius连接本地虚拟机与虚拟机快照 1. Termius连接本地虚拟机2. 虚拟机快照与还原2.1 设置快照以及恢复 附录 1. Termius连接本地虚拟机 ifconfig -a 查看配置 连接成功 2. 虚拟机快照与还原 在学习阶段我们无法避免的可能损坏Linux操作系统。 如果损坏的话&#xff0c;重新…

PyTorch入门教学——在虚拟环境中安装Jupyter

1、简介 Jupyter Notebook是一个开源的web应用程序&#xff0c;可以使用它来创建和共享包含实时代码、方程、可视化和文本的文档。Jupyter Notebook是一个交互式笔记本&#xff0c;可以当作python编译器来使用。 2、安装 在安装Anaconda时是自带了Jupyter Notebook的&#x…

C++ wpf自制软件打包安装更新源码实例

程序示例精选 C wpf自制软件打包安装更新源码实例 如需安装运行环境或远程调试&#xff0c;见文章底部个人QQ名片&#xff0c;由专业技术人员远程协助&#xff01; 前言 这篇博客针对《C wpf自制软件打包安装更新源码实例》编写代码&#xff0c;代码整洁&#xff0c;规则&…

分布式存储系统——ceph

目录 一、分布式存储类型 1、块存储 2、文件存储 3、对象存储 二、ceph概述 1、ceph简介 2、ceph的优势 3、ceph架构 1&#xff09;RADOS 基础存储系统&#xff08;Reliab1e&#xff0c;Autonomic&#xff0c;Distributed object store 2&#xff09;LIBRADOS 基础库 …

【Python搜索算法】深度优先搜索(DFS)算法原理详解与应用,示例+代码

目录 1 基本原理 2 DFS算法流程 3 时间复杂度 4 空间复杂度 5 DFS算法应用案例&#xff1a; 5.1 解决路径查找问题 5.2 解决图的连通性问题 5.3 拓扑排序 5.4 在树结构中进行深度遍历 深度优先搜索&#xff08;DFS&#xff09;是一种重要的图遍历算法&#xff0c;用…

【C语言】.c源文件从编译到链接生成可执行程序的过程

本篇文章目录 1. 过程概览2. 编译与链接2.1 预编译/预处理2.2 编译2.3 汇编2.4 链接 3. 执行/运行环境 1. 过程概览 编译到链接是c语言的翻译环境&#xff0c;c语言还有执行环境。 组成一个程序的每个源文件通过编译过程分别转换成目标代码&#xff08;object code&#xff09;…

2.Vue-从零开始搭建一个vue项目

题记 从零开始搭建一个vue项目&#xff0c;以下是操作的全过程。 安装Vue CLI脚手架 打开终端&#xff0c;运行以下命令全局安装Vue CLI脚手架&#xff1a; npm install -g vue/cli 查看 Vue CLI脚手架版本&#xff1a; vue -V 注意&#xff1a;查看vue版本的命令不是vue -V&a…

安捷伦N8485A射频传感器26.5GHz

安捷伦N8485A射频传感器 N8485A 是 Agilent 使用的 26.5 GHz 0.1 瓦射频传感器。电子测试设备传感器测量波形的功率&#xff0c;例如多音和调制射频 (RF) 波形。传感器使用二极管检测器收集高度精确的调制测量值。 用于存储校准系数的 EEPROM 消除了手动输入 10 MHz 至 26.5 GH…

15 | JPA 对 Web MVC 开发者做了哪些支持

我们使用 Spring Data JPA 的时候&#xff0c;一般都会用到 Spring MVC&#xff0c;Spring Data 对 Spring MVC 做了很好的支持&#xff0c;体现在以下几个方面&#xff1a; 支持在 Controller 层直接返回实体&#xff0c;而不使用其显式的调用方法&#xff1b;对 MVC 层支持标…

解读 | 自动驾驶系统中的多视点三维目标检测网络

原创 | 文 BFT机器人 01 背景 多视角三维物体检测网络&#xff0c;用于实现自动驾驶场景高精度三维目标检测&#xff0c;该网络使用激光雷达点云和RGB图像进行感知融合&#xff0c;以预测定向的三维边界框&#xff0c;相比于现有技术&#xff0c;取得了显著的精度提升。同时现…

树莓派:64位 RPI OS(Bookworm) 更换国内源

几天前新的RPI OS发布了。官方的发版说明里明确注明已经基于Debian Bookworm了。总的来说切到国内源&#xff08;清华&#xff09;跟Bullseye差不多&#xff0c;细节上只有一丢丢不同&#xff08;non-free变成了non-free-firmware&#xff09;。 老规矩&#xff0c;仍然是修改…

华为数通方向HCIP-DataCom H12-831题库(单选题:241-260)

第241题 某园区部署了IPV6进行业务测试,该网络中有4台路由器(R1R2、R3和R),运行OSPFV3实现Pv6网络的互联互通。有一台新的路由器R5需要接入网络进行测试,某工程师通过在R4的OSPFV3进程中引入直连路由,实现园区网内的设备能够访问R5的GEO/0/1口地址。关千该场景的描述,错误…

Spring(17) AopContext.currentProxy() 类内方法调用切入

目录 一、简介二、代码示例2.1 接口类2.2 接口实现类2.3 AOP切面类2.4 启动类&#xff08;测试&#xff09;2.5 执行结果 一、简介 背景&#xff1a; 在之前 Spring 的 AOP 用法中&#xff0c;只有代理的类才会被切入。例如&#xff1a;我们在 Controller 层调用 Service 的方式…

DID赛道前列的生物识别技术,开启Web3时代的大门—MXT

互联网发展的十字路口 互联网从上世纪90年代初发展至今&#xff0c;历经30年&#xff0c;她改变了整个人类的生活方式、沟通形式以及社会发展模式&#xff0c;她的影响早已渗透到了世界的各个角落。而如今&#xff0c;我们似乎正站在一个新的十字路口&#xff0c;一个互联网将…