0

0

PHP8.1readonly属性克隆难题如何解决?spatie/php-cloneable助你轻松搞定!

WBOY

WBOY

发布时间:2025-09-02 12:14:24

|

288人浏览过

|

来源于php中文网

原创

可以通过一下地址学习composer学习地址

php 8.1 发布之后,

readonly
属性无疑成为了许多开发者心头好。它强制了属性在初始化后不可更改,这对于构建可靠的不可变对象(immutable objects)和值对象(value objects)来说简直是福音。想象一下,你的
user
对象、
order
对象或者
configuration
对象,一旦创建,其核心属性就无法被意外修改,这大大提升了代码的健壮性和可预测性。

然而,在实际开发中,我们常常会遇到一个看似矛盾的需求:我有一个不可变对象,但我想基于它创建一个“新版本”,仅仅修改其中一两个属性,而保持原始对象不变。例如,一个

Post
对象,我想创建一个新的
Post
实例,它拥有相同的内容,但标题略有不同。

class Post
{
    public readonly string $title;
    public readonly string $author;
    public readonly string $content;

    public function __construct(string $title, string $author, string $content)
    {
        $this->title = $title;
        $this->author = $author;
        $this->content = $content;
    }
}

$originalPost = new Post('旧标题', '张三', '这是一篇旧文章的内容。');

// 试图克隆并修改标题,但 readonly 属性不允许重新赋值!
// $newPost = clone $originalPost;
// $newPost->title = '新标题'; // 这会抛出错误!

直接对

readonly
属性进行重新赋值显然是不被允许的。那么,难道每次都需要手动创建一个全新的对象,把所有未修改的属性一一复制过去吗?这不仅繁琐,而且容易出错,尤其当对象属性很多时,简直是噩梦。这种“克隆并修改”的需求,在函数式编程范式中被称为“withers”方法,它允许我们基于现有对象创建新对象,同时修改特定属性。

救星驾到:
spatie/php-cloneable

正当我为这种重复而无趣的代码感到沮丧时,开源社区再次展现了它的强大力量。

spatie/php-cloneable
这个 Composer 包,正是为了解决 PHP 8.1 中
readonly
属性的克隆难题而生。它提供了一个简洁优雅的 Trait,让你能够轻松地实现带有修改功能的克隆。

这个包的核心思想是:通过一个

with
方法,以“不可变更新”的方式,基于当前对象创建一个新的对象实例,并允许你指定要修改的属性值。

立即学习PHP免费学习笔记(深入)”;

码上飞
码上飞

码上飞(CodeFlying) 是一款AI自动化开发平台,通过自然语言描述即可自动生成完整应用程序。

下载

如何使用
spatie/php-cloneable

首先,通过 Composer 轻松安装它:

composer require spatie/php-cloneable

接下来,在你的类中引入

Spatie\Cloneable\Cloneable
Trait 即可:

use Spatie\Cloneable\Cloneable;

class Post
{
    use Cloneable; // 引入 Cloneable Trait

    public readonly string $title;
    public readonly string $author;
    public readonly string $content;

    public function __construct(string $title, string $author, string $content)
    {
        $this->title = $title;
        $this->author = $author;
        $this->content = $content;
    }
}

$originalPost = new Post('旧标题', '张三', '这是一篇旧文章的内容。');

// 现在,我们可以使用 with 方法来创建一个新 Post 实例,并修改其标题
$newPost = $originalPost->with(title: '新标题'); // 注意:这里必须使用命名参数!

echo "原始文章标题: " . $originalPost->title . PHP_EOL; // 输出: 旧标题
echo "新文章标题: " . $newPost->title . PHP_EOL;       // 输出: 新标题

// 也可以同时修改多个属性
$postByLiSi = $originalPost->with(title: '李四的文章', author: '李四');
echo "李四的文章标题: " . $postByLiSi->title . ", 作者: " . $postByLiSi->author . PHP_EOL;

// 为了更好的可读性和封装性,你可以在类中定义特定的 with* 方法
class PostWithHelpers
{
    use Cloneable;

    public readonly string $title;
    public readonly string $author;
    public readonly string $content;

    public function __construct(string $title, string $author, string $content)
    {
        $this->title = $title;
        $this->author = $author;
        $this->content = $content;
    }

    public function withTitle(string $title): self
    {
        return $this->with(title: $title);
    }

    public function withAuthor(string $author): self
    {
        return $this->with(author: $author);
    }
}

$anotherPost = new PostWithHelpers('原创标题', '王五', '内容...');
$modifiedPost = $anotherPost->withTitle('修改后的标题')->withAuthor('赵六');

echo "修改后的文章标题: " . $modifiedPost->title . ", 作者: " . $modifiedPost->author . PHP_EOL;

spatie/php-cloneable
with
方法会在底层创建一个新的对象实例,然后将原始对象的所有属性复制过去,最后再用你提供的参数覆盖对应的属性。由于它在内部巧妙地处理了
readonly
属性的限制,你无需担心任何错误。

优势与实际应用效果

  1. 优雅地处理不可变对象更新: 这是其最核心的优势。它让 PHP 8.1 的
    readonly
    属性与“克隆并修改”的需求完美结合,避免了手动复制属性的繁琐和潜在错误。
  2. 代码更清晰、意图更明确: 使用
    with(propertyName: $value)
    或自定义的
    withPropertyName($value)
    方法,代码的意图一目了然,明确表示我们正在基于现有对象创建一个新版本。
  3. 提高代码可维护性: 当你的对象属性发生变化时,你只需要修改
    with
    方法的调用或对应的
    with*
    辅助方法,而不需要修改所有手动复制属性的地方。
  4. 适用于多种场景: 无论是构建值对象、配置对象,还是在 DDD 中处理聚合根的不可变状态,
    spatie/php-cloneable
    都能提供极大的便利。它让你的代码在享受
    readonly
    带来的安全性的同时,保持了应有的灵活性。

小提示

需要注意的是,

spatie/php-cloneable
with
方法执行的是浅克隆。这意味着如果你的对象中包含其他对象引用,那么这些嵌套的对象并不会被递归克隆,而是会共享同一个引用。在大多数情况下这已经足够,但如果需要深克隆,你可能需要额外的处理。

总结

spatie/php-cloneable
是一个虽小但功能强大的 Composer 包,它巧妙地解决了 PHP 8.1
readonly
属性在对象克隆和修改时遇到的痛点。通过引入一个简单的 Trait,它让不可变对象的使用变得更加灵活和愉快,大大提升了开发效率和代码质量。如果你正在使用 PHP 8.1 并拥抱不可变性,那么这个库绝对值得你尝试!

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
composer是什么插件
composer是什么插件

Composer是一个PHP的依赖管理工具,它可以帮助开发者在PHP项目中管理和安装依赖的库文件。Composer通过一个中央化的存储库来管理所有的依赖库文件,这个存储库包含了各种可用的依赖库的信息和版本信息。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

153

2023.12.25

俄罗斯Yandex引擎入口
俄罗斯Yandex引擎入口

2026年俄罗斯Yandex搜索引擎最新入口汇总,涵盖免登录、多语言支持、无广告视频播放及本地化服务等核心功能。阅读专题下面的文章了解更多详细内容。

177

2026.01.28

包子漫画在线官方入口大全
包子漫画在线官方入口大全

本合集汇总了包子漫画2026最新官方在线观看入口,涵盖备用域名、正版无广告链接及多端适配地址,助你畅享12700+高清漫画资源。阅读专题下面的文章了解更多详细内容。

35

2026.01.28

ao3中文版官网地址大全
ao3中文版官网地址大全

AO3最新中文版官网入口合集,汇总2026年主站及国内优化镜像链接,支持简体中文界面、无广告阅读与多设备同步。阅读专题下面的文章了解更多详细内容。

79

2026.01.28

php怎么写接口教程
php怎么写接口教程

本合集涵盖PHP接口开发基础、RESTful API设计、数据交互与安全处理等实用教程,助你快速掌握PHP接口编写技巧。阅读专题下面的文章了解更多详细内容。

2

2026.01.28

php中文乱码如何解决
php中文乱码如何解决

本文整理了php中文乱码如何解决及解决方法,阅读节专题下面的文章了解更多详细内容。

4

2026.01.28

Java 消息队列与异步架构实战
Java 消息队列与异步架构实战

本专题系统讲解 Java 在消息队列与异步系统架构中的核心应用,涵盖消息队列基本原理、Kafka 与 RabbitMQ 的使用场景对比、生产者与消费者模型、消息可靠性与顺序性保障、重复消费与幂等处理,以及在高并发系统中的异步解耦设计。通过实战案例,帮助学习者掌握 使用 Java 构建高吞吐、高可靠异步消息系统的完整思路。

8

2026.01.28

Python 自然语言处理(NLP)基础与实战
Python 自然语言处理(NLP)基础与实战

本专题系统讲解 Python 在自然语言处理(NLP)领域的基础方法与实战应用,涵盖文本预处理(分词、去停用词)、词性标注、命名实体识别、关键词提取、情感分析,以及常用 NLP 库(NLTK、spaCy)的核心用法。通过真实文本案例,帮助学习者掌握 使用 Python 进行文本分析与语言数据处理的完整流程,适用于内容分析、舆情监测与智能文本应用场景。

24

2026.01.27

拼多多赚钱的5种方法 拼多多赚钱的5种方法
拼多多赚钱的5种方法 拼多多赚钱的5种方法

在拼多多上赚钱主要可以通过无货源模式一件代发、精细化运营特色店铺、参与官方高流量活动、利用拼团机制社交裂变,以及成为多多进宝推广员这5种方法实现。核心策略在于通过低成本、高效率的供应链管理与营销,利用平台社交电商红利实现盈利。

122

2026.01.26

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
第二十四期_PHP8编程
第二十四期_PHP8编程

共86课时 | 3.4万人学习

成为PHP架构师-自制PHP框架
成为PHP架构师-自制PHP框架

共28课时 | 2.5万人学习

第二十三期_PHP编程
第二十三期_PHP编程

共93课时 | 6.9万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号