从0开始学PHP面向对象内容之(常用魔术方法续二)

在这里插入图片描述

哈喽朋友们,I am comming,今天把剩下的常用魔术方法讲了,话不多说开始正文

常用魔术方法(续二)

一、__toString()

__toString() 是 PHP 提供的一个魔术方法,用于定义对象在被转换为字符串时的行为。它在某些场景下显得非常有用,因为它让开发者可以控制对象在输出、拼接、打印时显示的内容。下面是
__toString() 方法的详细解析和相关内容。

定义

public function __toString(): string

1、打印对象信息

class User {private $name;private $email;public function __construct($name, $email) {$this->name = $name;$this->email = $email;}public function __toString() {return "User: {$this->name}, Email: {$this->email}";}
}$user = new User("Alice", "alice@example.com");
echo $user; // 输出 "User: Alice, Email: alice@example.com"

2、 用作字符串拼接

class Address {private $street;private $city;public function __construct($street, $city) {$this->street = $street;$this->city = $city;}public function __toString(): string {return "{$this->street}, {$this->city}";}
}$address = new Address("123 Main St", "New York");
echo "Delivery Address: " . $address; // 输出 "Delivery Address: 123 Main St, New York"

3、调试和日志记录

__toString() 方法在调试时很有用,因为它可以让对象在被打印时提供更多上下文信息。

示例:
class Product {private $name;private $price;public function __construct($name, $price) {$this->name = $name;$this->price = $price;}public function __toString(): string {return "Product: {$this->name}, Price: $ {$this->price}";}
}$product = new Product("Laptop", 1200);
error_log((string)$product); // 写入日志:"Product: Laptop, Price: $ 1200"
实现注意事项
  1. 必须返回字符串:__toString() 必须返回字符串类型,否则会引发错误。
  2. 不可抛出异常:在 PHP 5.2.0 之前,__toString() 抛出异常会导致致命错误。从 PHP 7.4 开始,__toString() 抛出的异常会被捕获并处理,但最好避免直接在方法中抛出异常。
  3. 复杂对象输出:在实现 __toString() 时,避免输出过于复杂或难以理解的内容。保持输出简洁、清晰,能传达对象的关键信息即可。
典型应用场景:
1、将对象用于模板引擎

很多模板引擎可以直接将对象嵌入到模板中。实现 __toString() 后,可以简化模板渲染过程。

class Page {private $title;public function __construct($title) {$this->title = $title;}public function __toString(): string {return "<h1>{$this->title}</h1>";}
}$page = new Page("Welcome to My Website");
echo $page; // 输出 "<h1>Welcome to My Website</h1>"
2、对象键生成

在缓存系统中,将对象作为缓存键的一部分时,__toString() 可以用来生成可读和唯一的字符串表示。

class Session {private $sessionId;public function __construct($sessionId) {$this->sessionId = $sessionId;}public function __toString(): string {return $this->sessionId;}
}$session = new Session("abc123");
$cacheKey = "session_" . $session; // 结果为 "session_abc123"
限制和注意事项
  1. 不可滥用:__toString() 应该用来返回对象的简单字符串表示,不要执行过多的逻辑或访问外部资源。
  2. 安全性:在实现 __toString() 时,不要返回敏感信息,比如密码或密钥。
  3. 性能:复杂的字符串拼接和格式化可能影响性能,因此应尽量保持 __toString() 方法的高效性。

总结

__toString() 是 PHP 提供的一个强大工具,用于在字符串上下文中提供对象的自定义表示。它适合用于打印、日志记录、模板渲染等场景。通过合理的实现,可以提高代码的可读性和调试的便利性,但要注意性能和安全性。

二、__autoload()

__autoload() ,这个魔术方法我们会经常使用到是 ,PHP 中的一个魔术方法,用于在访问未定义的类时自动加载相应的类文件。
虽然 __autoload() 可以减少手动包含文件的繁琐工作,但它已经被标记为已废弃,从 PHP 7.2.0 开始被弃用并在 PHP 8.0.0 中被移除。取而代之的是更灵活的 spl_autoload_register() 方法。

基本定义

这里是引用__autoload() 是一个自动加载器函数,当访问一个尚未加载或未定义的类时会被调用。其定义如下:

function __autoload($className) {// 根据类名包含对应的文件include_once $className . '.php';
}

$className:被访问的类的名称。

限制和缺点

  1. 单一性:__autoload() 只能定义一次。如果有多个自动加载需求,__autoload() 无法同时满足,这使得它的灵活性不足。
  2. 已弃用:__autoload() 从 PHP 7.2.0 开始已被弃用,在 PHP 8.0.0 中被完全移除。建议使用 spl_autoload_register() 进行替代。
  3. 可扩展性差:__autoload() 不支持链式或多重自动加载器,而 spl_autoload_register() 支持注册多个自动加载器。

推荐替代方法:spl_autoload_register()

spl_autoload_register() 是一个更好的替代方法,它提供了更高的灵活性和扩展性。通过它,可以注册多个自动加载器并以队列的形式依次尝试加载。

示例:
spl_autoload_register(function ($className) {include_once 'classes/' . $className . '.php';
});spl_autoload_register(function ($className) {include_once 'lib/' . $className . '.php';
});

这种方式允许同时注册多个自动加载器,使得项目结构更具灵活性和可扩展性。

总结、

__autoload() 是一个简单的自动加载机制,但由于其单一性和扩展性不足已被弃用。
spl_autoload_register() 是更推荐的自动加载方法,支持注册多个加载器和自定义加载逻辑。
PSR-4 标准结合 spl_autoload_register() 是现代 PHP 项目的首选解决方案,用于高效和组织良好的类加载。
在现代开发中,强烈建议使用 spl_autoload_register() 和基于 PSR-4 的自动加载来替代 __autoload()。

三、__sleep()

__sleep() 是 PHP 的魔术方法,专门用于对象的序列化。当你尝试将对象使用 serialize() 函数进行序列化时,如果对象中定义了 __sleep() 方法,那么 __sleep() 会在序列化前被自动调用。

基本定义

__sleep() 方法在对象序列化时被调用,它的主要作用是指定哪些对象属性需要被序列化。

public function __sleep(): array
返回值必须返回一个数组,数组元素是要被序列化的属性的名称。如果返回其他类型,将会导致错误。

应用场景

1、优化序列化

有时对象中包含不需要序列化的数据,比如数据库连接、资源句柄或大数据对象。通过 __sleep()
方法,你可以选择性地序列化必要的属性,优化序列化的存储空间和性能。

2、 清理工作:

在对象序列化之前执行一些清理工作,比如关闭数据库连接或释放文件资源。

基本用法示例
class User {public $name;public $email;private $password;private $connection; // 假设是数据库连接对象public function __construct($name, $email, $password) {$this->name = $name;$this->email = $email;$this->password = $password;$this->connection = new DatabaseConnection(); // 示例连接}public function __sleep(): array {// 在序列化之前,关闭数据库连接$this->connection->close();// 仅序列化 name 和 emailreturn ['name', 'email'];}
}$user = new User("John Doe", "john@example.com", "secret");
$serializedData = serialize($user); // 调用 __sleep(),返回仅包含 name 和 email 的数据
使用注意事项
  1. 返回值类型:__sleep() 必须返回数组,如果返回其他数据类型将会导致错误。
  2. 数据一致性:在 __sleep() 中清理资源时,确保不会破坏对象的完整性。对象在重新使用 unserialize() 解序列化时应能够恢复到合理的状态。
  3. 替代方案:在现代 PHP 应用中,Serializable 接口提供了更细粒度的序列化控制,允许自定义 serialize() 和 unserialize() 方法。
  4. 通常 __sleep() 与 __wakeup() 方法配合使用。__wakeup() 方法在使用 unserialize() 解序列化对象时被调用,用于恢复对象的状态或重新连接资源。
示例:
public function __wakeup() {// 在解序列化后重新连接数据库$this->connection = new DatabaseConnection();
}
总结

__sleep() 用于在对象序列化之前做清理工作并选择性序列化对象属性。
__wakeup() 用于在对象解序列化时恢复对象的状态。
__sleep() 提高了对象序列化的效率和安全性,通过避免序列化不需要或敏感的数据。
在 PHP 中,__sleep() 是处理对象序列化的重要工具,特别是在管理资源、减少数据冗余和保护敏感信息时。

四、__wakeup()

__wakeup() 是 PHP 的魔术方法,与 __sleep() 相对应,用于对象解序列化时的处理。当对象通过 unserialize() 函数被解序列化时,__wakeup() 方法会被自动调用。它通常用于恢复对象的状态,例如重新建立数据库连接或初始化某些未序列化的资源。

基本定义

__wakeup() 方法的声明如下:

public function __wakeup(): void
返回值:__wakeup() 不应返回任何值。

用途

  1. 恢复资源或连接:在对象序列化的过程中,某些资源或外部连接(如数据库连接、文件句柄等)不能被序列化。因此,__wakeup() 通常用来在对象解序列化后重新建立这些连接。
  2. 初始化数据:用于在对象解序列化后重新初始化某些必须的数据,以确保对象能正常工作。
  3. 安全性:在一些应用中,__wakeup() 可以用于验证或检查对象的状态,确保解序列化的数据是合法和安全的。

常见应用场景

场景 1:恢复数据库连接 当对象包含数据库连接信息时,__wakeup()
可以在解序列化后重新建立连接,保证对象在使用时不会因为缺少连接而出错。

场景 2:重建外部资源 如果对象涉及到文件句柄或其他外部资源,__wakeup() 方法可以用于重新打开文件或恢复资源。

场景 3:初始化缓存或状态 如果对象有缓存机制或在初始化时需要加载某些数据,__wakeup()
可以在解序列化后加载这些数据,保证对象的一致性和可用性。

注意事项

安全性:在使用 __wakeup() 时,注意防止对象注入攻击。反序列化不可信的数据时,攻击者可能通过操纵对象的属性进行破坏。因此,必须在
__wakeup() 中进行必要的验证和检查。 性能:在 __wakeup() 中恢复复杂的资源或进行大量操作可能会影响性能。因此,应确保恢复逻辑足够高效。 限制:__wakeup() 只会在使用
unserialize() 函数时被调用,直接创建对象实例不会触发 __wakeup()。

完整示例

class FileHandler {private $filePath;private $fileHandle;public function __construct($path) {$this->filePath = $path;$this->openFile();}private function openFile() {$this->fileHandle = fopen($this->filePath, 'r');}public function __sleep() {// 在序列化时关闭文件句柄fclose($this->fileHandle);return ['filePath']; // 仅保存文件路径}public function __wakeup() {// 在解序列化时重新打开文件$this->openFile();}public function readFile() {if ($this->fileHandle) {return fread($this->fileHandle, filesize($this->filePath));}return null;}
}// 使用示例
$fileHandler = new FileHandler('example.txt');
$serializedHandler = serialize($fileHandler);
$unserializedHandler = unserialize($serializedHandler);
echo $unserializedHandler->readFile();

总结

__wakeup() 方法用于对象解序列化时恢复状态或重新建立资源。
常用于恢复数据库连接、文件句柄等无法被序列化的资源。
应注意安全性和性能,尤其在处理不可信数据时需进行验证和检查。
配合 __sleep() 方法,__wakeup() 可以有效管理对象的序列化和解序列化过程,使对象在序列化后的状态保持完整和一致。

总结

大家不难发现 很多魔术方法都是成对出现的,所以在理解和使用的时候要注意,我这边写的只能说是包含大部分的定义,使用场景,简单示例,具体的使用场景和使用方式还是要结合实际,进行灵活运用,祝大家在学习编程的路上越走越远,越走越宽

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

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

CSS 技巧:如何让 div 完美填充 td 高度

引言 一天哈比比突然冒出一个毫无理头的一个问题: 本文就该问题进行展开… 原文链接: 昆仑虚F2E 一、需求说明 大致需求如下, 当然这里做了些简化 有如下初始代码: 一个自适应的表格每个单元格的宽度固定 200px每个单元格高度则是自适应每个单元格内是一个 div 标签, div 标签…

清华、国科大、智谱团队提出LongReward:利用AI反馈改进长文本大语言模型

长文本&#xff08;Long-context&#xff09;大模型性能的优劣&#xff0c;在很大程度上取决于其能否全面理解长上下文场景下的复杂信息。 然而&#xff0c;现有的合成有监督微调&#xff08;SFT&#xff09;数据由于缺少人类核验&#xff0c;往往会影响长文本大模型的性能&am…

2024 年 10 款替代 Postman 的工具,有免费有开源

10 款替代 Postman 的工具&#xff0c;有免费有开源&#xff1a; 工具名称支持的系统是否免费是否开源ApifoxWindows, macOS, Linux免费否Yapi无限制是是InsomniaWindows, macOS, Linux免费版付费版是Hoppscotch浏览器是是SoapUIWindows, macOS, Linux免费版付费版是Katalon S…

IDEA报包不存在,但实际存在

IDEA版本2024.2.1 现象 在IDEA里启动运行项目&#xff0c;报某个类有问题&#xff0c;引入的包不存在。 点击这个引入的包&#xff0c;可以看到它在左侧外部库里存在。 试过的无效方法 双击ctrl&#xff0c;在弹出框中mvn idea:idea在文件里&#xff0c;清空缓存并重启在右…

从词向量到多模态嵌入:大型语言模型的技术、应用及未来方向

索引词—大型语言模型、词嵌入、上下文嵌入、多模态表示、自然语言处理 摘要—词嵌入和语言模型通过将语言元素表示在连续向量空间中&#xff0c;彻底改变了自然语言处理&#xff08;NLP&#xff09;。本综述回顾了分布假设和上下文相似性等基础概念&#xff0c;追溯了从稀疏表…

超越传统:探索ONLYOFFICE的革命性办公新纪元

目录 &#x1f341;引言 &#x1f341;一、ONLYOFFICE产品简介 &#xff08;一&#xff09;、介绍 &#xff08;二&#xff09;、基本功能简介 &#x1f341;二、核心功能具体介绍 1、编辑操作 2、文本与段落&#xff1a; 3、样式与图形&#xff1a; 4、表格与图表&…

【GESP】C++一级真题(202406)luogu-B4001,立方数

2024年6月GESP一级真题。循环类问题。 题目题解详见&#xff1a;【GESP】C一级真题(202406)luogu-B4001&#xff0c;立方数 | OneCoder https://www.coderli.com/gesp-1-luogu-b4001/https://www.coderli.com/gesp-1-luogu-b4001/ C GESP专项交流频道&#xff1a;GESP学习交…

SAP 创建物料主数据报错:估价范围3010还没有生产式的物料帐簿

通过接口创建物料主数据&#xff08;模拟MM01&#xff09;&#xff0c;报错如图&#xff1a; 处理方案1&#xff1a;&#xff08;我的不行&#xff0c;提示已经是生产的&#xff09; 将评估范围的物料分类账设置为生产 事务码: CKMSTART - 物料分类帐的生产开始 处理方案2&a…

Python | Leetcode Python题解之第560题和为K的子数组

题目&#xff1a; 题解&#xff1a; class Solution:def subarraySum(self, nums: List[int], k: int) -> int:dic{0:1}sums,res0,0for num in nums:sumsnumresdic.get(sums-k,0)dic[sums]dic.get(sums,0)1return res

sql注入之二次注入(sqlilabs-less24)

二阶注入&#xff08;Second-Order Injection&#xff09;是一种特殊的 SQL 注入攻击&#xff0c;通常发生在用户输入的数据首先被存储在数据库中&#xff0c;然后在后续的操作中被使用时&#xff0c;触发了注入漏洞。与传统的 SQL 注入&#xff08;直接注入&#xff09;不同&a…

AOA-LSTM多输入回归预测|算术优化算法-长短期神经网络|Matlab

目录 一、程序及算法内容介绍&#xff1a; 基本内容&#xff1a; 亮点与优势&#xff1a; 二、实际运行效果&#xff1a; 三、方法原理介绍&#xff1a; 四、完整代码数据下载&#xff1a; 一、程序及算法内容介绍&#xff1a; 基本内容&#xff1a; 本代码基于Matlab平…

认知战认知作战:郑成功收复台湾的认知作战分析与策略

认知战认知作战&#xff1a;郑成功收复台湾的认知作战分析与策略 认知战认知作战&#xff1a;郑成功收复台湾的认知作战分析与策略 关键词&#xff1a;认知作战,新质生产力,人类命运共同体,认知战,认知域,认知战研究中心,认知战争,认知战战术,认知战战略,认知域作战研究,认知…

单细胞技术加持,扩增子测序重回高大上| 一区微生物多组学研究新思路!

俗称“万金油”的扩增子技术已经再难发出好文章了&#xff1f;实则不然!关联高端霸气上档次的单细胞转录组技术&#xff0c;扩增子研究依旧可以焕发新生机&#xff0c;重回高大上。 近日&#xff0c;檀国大学在《communications biology》上最新发表的文章打破了传统微生物组分…

遗传算法与深度学习实战(23)——利用遗传算法优化深度学习模型

遗传算法与深度学习实战&#xff08;23&#xff09;——利用遗传算法优化深度学习模型 0. 前言1. 神经进化2. 使用遗传算法作为深度学习优化器小结系列链接 0. 前言 神经进化涵盖了所有用于改进深度学习的进化算法。更具体地说&#xff0c;神经进化用来定义应用于深度学习的特…

Hbase入门

目录 Hbase逻辑结构 一、基础知识 1. Hbase逻辑结构 行键(Rowkey)&#xff1a;唯一标识一行数据&#xff0c;按照字典序(row_key1 < row_key11 < rowkey2)排列.列Col&#xff1a;数据记录的一条属性列族&#xff1a;将多列划分为一类&#xff0c;视为一个列族。例如上图…

三维模型-管道-建模规范

一、阀门模型处理 Max中的阀门模型,备份之前可拆分的阀门模型。 将需要选择的阀门,合并(不打组)成一个模型。 材质在不同模型上,按照需求分好不同的材质 例如:阀门、管道,需要分成不同的材质和相对应的不同模型。 二、管道模型处理 1) 普通管道 默认展开UV ;2) 流…

golang go语言 组建微服务架构详解 - 代码基于开源框架grpc+nacos服务管理配置平台

整体介绍&#xff1a; 本文主要介绍如何用go语言 来组建微服务的框架&#xff0c;grpc服务管理 示例框架 代码由grpcnacos go sdk 组成。 grpc负责将调用序列化并传递到远端&#xff0c;nacos负责服务发现和服务管理。 grpc和nacos都是开源产品。代码复制下来就能跑。 微服…

open3d

open3d open3d用于 3D 数据处理的现代库。 简介 Open3D 是一个开源库&#xff0c;支持快速开发处理 3D 数据的软件。Open3D 前端公开了一组精心挑选的 C 和 Python 数据结构和算法。后端经过高度优化&#xff0c;并设置为并行化。Open3D 是从零开始开发的&#xff0c;具有一更…

一个轻量级RAG文本切块项目Chonkie

**Chonkie&#xff1a;**实用的RAG分块库&#xff0c;轻量级、速度快&#xff0c;可随时对文本进行分块 支持的方法 Chonkie 提供了多个分块器&#xff0c;可高效地为RAG应用程序拆分文本。以下是可用分块器的简要概述&#xff1a; TokenChunker&#xff1a;将文本分割成固定大…

如何通过AB测试找到最适合的Yandex广告内容

想要在Yandex上找到最能吸引目标受众的广告内容&#xff0c;A/B测试是一个不可或缺的步骤。通过对比不同版本的广告&#xff0c;我们可以发现哪些元素最能引起用户的共鸣。首先&#xff0c;设计两个或多个广告版本&#xff0c;确保每个版本在标题、文案、图片等关键元素上有所不…