沉睡的木乃伊: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,一经查实,立即删除!

相关文章

Python 的基本数据类型

三、Python 的基本数据类型 1、字符串 字符串英文 string ,是 python 中随处可见的数据类型,字符串的识别也非常的简单,就是用「引号」括起来的。 引号包括单引号 ,双引号 " " 和 三引号 ,比如 abc ,"123" 等等。 这里请注意,单引号 或双引…

Python- JSON-RPC创建一个远程过程调用

我们使用JSON-RPC创建一个远程过程调用的例子&#xff0c;我们将使用jsonrpcserver库和Flask框架创建一个后端服务&#xff0c;并使用jsonrpcclient作为客户端。这个例子将包括&#xff1a; 一个计算服务&#xff0c;提供加、减、乘、除四个方法。错误处理&#xff1a;除数为零…

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

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

Python机器学习零基础理解AffinityPropagation聚类

如何解决社交媒体上的好友推荐问题? 想象一下,一个社交媒体平台希望提供更加精准的好友推荐功能,让用户能更容易地找到可能成为好友的人。这个问题看似简单,但当面对数百万甚至数千万的用户时,手动进行好友推荐就变得几乎不可能。 解决这个问题的一个方案就是使用机器学…

百度Apollo自动驾驶

百度从2013年开始布局自动驾驶领域&#xff0c;十年来一直坚持压强式的、马拉松式的研发投入&#xff0c;以技术创新驱动长期发展。百度Apollo L4级自动驾驶运营测试里程累计已超5000万公里&#xff0c;拥有自动驾驶专利族超4600件&#xff0c;其中高级别自动驾驶专利族数全球第…

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…

【全栈开发指南】打包sentinel-dashboard镜像推送到Docker Hub镜像仓库

Docker Hub是Docker官方提供的一个公共的镜像仓库&#xff0c;它是一个中央的存储库&#xff0c;用户可以在其中存储和分享Docker镜像。通过Docker Hub&#xff0c;用户可以方便地搜索、下载和共享Docker镜像&#xff0c;并可以将它们用于构建和部署容器化应用程序。Docker Hub…

java 获取 request

第一种&#xff0c;通过springmvc,参数注入 PostMapping(value "/xxx") public Result xxx(HttpServletRequest request) {}第二种&#xff0c;通过RequestContextHolder获取 这种方式在项目任何地方都可以拿到&#xff0c;只要Request已经注入 private static Htt…

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

视频及资料链接&#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;重新…

【WIFI】【WPS】基础介绍(主要根据sniffer log角度和kernel log去介绍)

Wps简介 WPS(Wi-Fi Protected Setup,WiFi保护设置),它是由WiFi联盟组织实施的可选认证项目,它主要致力于简化无线网络设置及无线网络加密等工作。 一般情况下,用户在新建一个无线网络时,为了保证无线网络的安全,都会对无线网络名称(SSID)和无线加密方式进行…

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;规则&…

rpx是微信小程序独有的,解决屏幕自适应的尺寸单位

rpx&#xff1a; 是微信小程序独有的&#xff0c;解决屏幕自适应的尺寸单位 可以根据屏幕宽度进行自适应&#xff0c;不论屏幕大小&#xff0c;规定屏幕宽为 750rpx&#xff0c;通过rpx设置元素和字体大小&#xff0c;小程序在不同尺寸的屏幕上可以自适应适配 rpx与px之间的换…

分布式存储系统——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 基础库 …

【sv】 pack/unpack stream

https://www.amiq.com/consulting/2017/05/29/how-to-pack-data-using-systemverilog-streaming-operators/ https://www.amiq.com/consulting/2017/06/23/how-to-unpack-data-using-the-systemverilog-streaming-operators/

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

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