只读属性遇上序列化难题,PHP 8.3开发者必须掌握的5种解决方案

第一章:PHP 8.3只读属性与序列化挑战概述

PHP 8.3 引入了对只读属性(readonly properties)的增强支持,允许开发者在类中声明不可变的属性,从而提升数据完整性与代码可维护性。这一特性在构建值对象、DTO(数据传输对象)或配置类时尤为有用。然而,当涉及对象序列化(如使用 `serialize()` 和 `unserialize()`)时,只读属性带来了新的挑战。

只读属性的基本用法

只读属性一旦被赋值,便无法在后续修改,包括构造函数之外的任何地方。定义方式如下:
// 定义包含只读属性的类
class User {
    public function __construct(
        public readonly string $id,
        public readonly string $name
    ) {}
}
该代码中,`$id` 和 `$name` 在对象创建后不可更改,确保实例状态的稳定性。

序列化中的问题

PHP 的反序列化机制在重建对象时绕过构造函数,直接填充属性值。这导致两个主要问题:
  • 只读属性在反序列化过程中可能被非法重写
  • 违反了只读语义,破坏对象封装性
为应对该问题,PHP 8.3 要求开发者显式实现 `__serialize()` 和 `__unserialize()` 魔术方法,以控制序列化行为。

推荐的解决方案

通过自定义序列化逻辑,可在反序列化时重新调用构造函数或验证状态。例如:
class User {
    public function __construct(
        public readonly string $id,
        public readonly string $name
    ) {}

    public function __serialize(): array {
        return ['id' => $this->id, 'name' => $this->name];
    }

    public function __unserialize(array $data): void {
        // 通过构造函数保证只读属性初始化
        $this->__construct($data['id'], $data['name']);
    }
}
此方式确保只读属性仍通过构造函数赋值,避免直接写入,从而维持语言级别的只读约束。
特性PHP 8.2 及之前PHP 8.3
只读属性支持仅支持初始化后不可变增强支持,配合序列化钩子
反序列化安全性存在绕过风险需手动实现保护逻辑

第二章:理解只读属性的底层机制与反射原理

2.1 只读属性在PHP 8.3中的实现细节

PHP 8.3 引入了对只读属性的增强支持,允许在运行时动态构造只读对象,并确保其深层不可变性。
基本语法与限制
#[\AllowDynamicProperties]
class User {
    public function __construct(
        public readonly string $name,
        public readonly array $roles
    ) {}
}
上述代码定义了一个包含只读属性的类。$name 和 $roles 在初始化后无法修改,尝试赋值将抛出 Error。
深层不变性机制
当只读属性包含数组或对象时,PHP 8.3 确保其“深层”数据不被更改:
  • 标量值直接锁定
  • 嵌套对象也必须声明为只读以保证完整性
  • 数组元素若为对象,需独立配置只读状态

2.2 利用ReflectionClass获取只读属性元信息

PHP 8.1 引入了只读属性(readonly properties),确保属性在初始化后不可更改。通过 `ReflectionClass`,可在运行时动态获取这些属性的元信息。
反射获取只读属性
使用 `ReflectionProperty::isReadOnly()` 方法可判断属性是否为只读:
<?php
class User {
    public readonly string $name;
    public int $age;
}

$ref = new ReflectionClass(User::class);
foreach ($ref->getProperties() as $prop) {
    echo $prop->getName() . ' 是只读?' . 
         ($prop->isReadOnly() ? '是' : '否') . "\n";
}
?>
上述代码输出: ``` name 是只读?是 age 是只读?否 ``` `ReflectionProperty` 提供了对类属性的完整访问能力,`isReadOnly()` 返回布尔值,标识该属性是否声明为 `readonly`,便于构建序列化、验证或ORM等需要属性元数据的系统。

2.3 反射修改只读属性的可行性分析与限制

在某些高级语言中,反射机制允许运行时动态访问和修改对象成员,包括私有或只读属性。然而,这种能力并非无约束。
语言层面的限制
以 Go 为例,反射无法直接修改非导出字段(小写开头),即使通过指针获取地址:

type Config struct {
    readOnlyValue int
}
c := Config{readOnlyValue: 42}
v := reflect.ValueOf(&c).Elem().Field(0)
if v.CanSet() {
    v.SetInt(100) // 不会执行,因字段非导出
}
上述代码中,v.CanSet() 返回 false,表明该字段不可写。
安全与设计原则的制约
  • Java 的安全管理器可禁止反射访问私有成员;
  • .NET 中 readonly 字段在构造函数外禁止修改,反射亦受此约束;
  • 多数现代框架通过封装和访问控制保护核心状态。
因此,尽管反射技术上可能突破部分封装,但语言规范和运行时安全策略构成了硬性边界。

2.4 运行时检查属性只读状态的实用技巧

在动态语言环境中,运行时判断对象属性是否为只读是保障数据安全的关键环节。通过反射机制可有效探知属性元信息。
使用反射检测属性特性
package main

import (
    "fmt"
    "reflect"
)

type Config struct {
    APIKey     string `readonly:"true"`
    Timeout    int    `readonly:"false"`
}

func IsReadOnly(obj interface{}, field string) bool {
    v := reflect.ValueOf(obj).Elem()
    t := v.Type()
    for i := 0; i < t.NumField(); i++ {
        if t.Field(i).Name == field {
            tag := t.Field(i).Tag.Get("readonly")
            return tag == "true"
        }
    }
    return false
}
上述代码利用 Go 的反射获取结构体字段标签,判断 readonly 标签值。若为 true,表示该属性在运行时应被保护,不可修改。
常见只读标识方式对比
方式语言支持运行时可读
Struct TagGo是
DecoratorsTypeScript是
AnnotationsJava是

2.5 反射结合属性类型约束的兼容性处理

在Go语言中,反射机制允许程序在运行时动态获取变量的类型信息并操作其值。当与泛型结合使用时,需特别注意类型约束与反射行为之间的兼容性。
类型断言与反射的交互
使用 reflect.Value.Interface() 获取值后,必须确保目标类型满足泛型约束条件,否则将引发运行时 panic。
func Process[T any](v T) {
    rv := reflect.ValueOf(v)
    if rv.Kind() == reflect.Struct {
        // 确保T符合预期结构体类型
        field := rv.FieldByName("ID")
        if field.IsValid() && field.CanInterface() {
            id := field.Interface().(int) // 显式断言需谨慎
        }
    }
}
上述代码中,field.Interface().(int) 的类型断言仅在结构体确实包含 int 类型的 ID 字段时安全。若泛型参数 T 不满足此隐式结构契约,程序将崩溃。
安全的类型兼容性检查
推荐在反射操作前进行类型验证:
  • 使用 reflect.TypeOf 比对期望类型
  • 通过 CanInterface 和 IsValid 判断字段可访问性
  • 优先采用类型开关(type switch)替代直接断言

第三章:序列化机制与只读属性的冲突解析

3.1 PHP原生序列化对只读属性的行为剖析

PHP原生序列化机制在处理只读(readonly)属性时表现出特定行为。自PHP 8.2起引入的`readonly`关键字用于限制属性仅可在构造函数中赋值,但序列化过程绕过此访问控制。
序列化与反序列化流程
class User {
    public function __construct(
        private readonly string $name
    ) {}
}

$user = new User("Alice");
$serialized = serialize($user);
$restored = unserialize($serialized);
echo $restored->getName(); // Fatal error: Uninitialized readonly property
上述代码在反序列化后无法访问`$name`,因构造函数未执行,只读属性未被显式初始化。
核心机制分析
  • 序列化时保存所有属性值,不论是否只读;
  • 反序列化时直接恢复属性状态,不调用构造函数;
  • 导致只读属性虽有值,但处于“未通过构造函数初始化”状态,违反语言设计语义。
该行为揭示了序列化与现代OOP特性的兼容性缺陷,需谨慎处理只读对象的持久化。

3.2 Unserialize时只读属性赋值失败的根源

在反序列化过程中,对象的构造函数通常不会被调用,导致只读属性(readonly properties)无法通过正常初始化流程赋值。PHP 在 unserialize() 时直接恢复属性值,绕过构造逻辑和访问控制检查。
触发场景示例
class User {
    public readonly string $role;
    
    public function __construct() {
        $this->role = 'guest';
    }
}
// unserialize会失败:Cannot modify readonly property
$payload = 'O:4:"User":1:{s:4:"role";s:5:"admin";}';
unserialize($payload);
上述代码试图在反序列化时直接写入 $role,但因该属性为只读且未经过构造函数初始化,PHP 运行时抛出致命错误。
底层机制分析
  • unserialize 操作不触发 __construct
  • 只读属性只能在构造函数中一次性赋值
  • 序列化数据中的属性会被直接写入对象存储,绕过访问控制
此行为暴露了序列化与现代OOP封装特性之间的兼容性缺陷。

3.3 自定义序列化接口应对只读限制的策略

在处理外部系统集成时,只读数据源常无法直接适配本地模型结构。通过实现自定义序列化接口,可灵活控制数据转换过程。
接口设计原则
  • 分离读写逻辑,确保只读数据不触发写操作
  • 封装字段映射,屏蔽源结构差异
  • 支持按需加载,提升序列化效率
代码实现示例
type ReadOnlyEntity struct {
    ID   string `json:"id"`
    Name string `json:"name"`
}

func (r *ReadOnlyEntity) Serialize() map[string]interface{} {
    return map[string]interface{}{
        "external_id": r.ID,
        "label":       r.Name,
    }
}
该方法将原始字段重新映射为外部系统所需格式,Serialize() 返回通用结构,便于后续统一处理。参数 ID 和 Name 来自只读实例,输出键名适配目标协议要求,避免直接暴露内部字段。

第四章:五种解决方案中的核心实践模式

4.1 方案一:构造函数注入配合序列化钩子

在实现安全可靠的依赖注入时,构造函数注入是保障对象实例化完整性的首选方式。通过将依赖项在对象创建阶段传入,可避免运行时的空指针风险。
序列化钩子的协同机制
Java 序列化过程中,可通过 readObject 钩子方法重建依赖关系,确保反序列化后仍持有有效的注入实例。

private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException {
    stream.defaultReadObject();
    // 重新注入依赖
    this.service = ApplicationContext.getBean(Service.class);
}
上述代码在反序列化完成后触发,手动恢复被 transient 修饰的依赖对象,保证业务逻辑连续性。
优势与适用场景
  • 确保构造时依赖完整性
  • 兼容 Java 原生序列化机制
  • 适用于会话状态持久化场景

4.2 方案二:利用__serialize和__unserialize魔法方法

在PHP中,__sleep 和 __wakeup 魔法方法可用于对象序列化与反序列化的控制。通过实现这两个方法,开发者可自定义对象在序列化前的清理逻辑及反序列化后的初始化操作。
序列化流程控制
class User {
    private $name;
    private $password;

    public function __sleep() {
        // 仅序列化name字段,排除敏感信息
        return ['name'];
    }

    public function __wakeup() {
        // 反序列化后重置敏感数据或资源连接
        $this->password = null;
    }
}
__sleep 返回需序列化的属性名数组,有效防止敏感字段被持久化;__wakeup 在对象重建时执行必要恢复逻辑,如关闭文件句柄或数据库连接。
适用场景对比
  • 适用于包含资源句柄或临时状态的对象
  • 增强安全性,避免敏感数据写入存储介质
  • 支持跨请求的状态一致性维护

4.3 方案三:通过对象模拟实现可变中间态

在复杂状态管理场景中,直接修改原始数据易导致不可追踪的副作用。为此,可通过对象模拟技术构建可变中间态,隔离变更影响范围。
模拟对象的设计思路
创建代理对象捕获所有属性访问与赋值操作,延迟写入原始数据源,从而实现变更前的状态快照。

const createProxyState = (target) => {
  const snapshot = { ...target };
  return new Proxy(target, {
    set(obj, prop, value) {
      console.log(`变更拦截: ${prop} = ${value}`);
      obj[prop] = value;
      return true;
    }
  });
};
上述代码通过 `Proxy` 捕获设值操作,在不侵入原逻辑的前提下记录变更行为。`snapshot` 保留初始状态,便于后续对比或回滚。
适用场景与优势
  • 表单编辑过程中的临时状态保存
  • 撤销/重做功能的基础支撑
  • 提升调试能力,清晰追踪状态流转路径

4.4 方案四:使用弱引用代理绕过只读限制

在某些运行时环境中,对象的只读属性限制可通过弱引用代理机制实现间接修改。该方案利用代理对象拦截对目标属性的访问,并通过弱引用维持与原对象的关联,避免内存泄漏。
核心实现逻辑

const createMutableProxy = (target) => {
  const weakRef = new WeakRef(target);
  return new Proxy({}, {
    get(_, prop) {
      const ref = weakRef.deref();
      return ref ? ref[prop] : undefined;
    },
    set(_, prop, value) {
      const ref = weakRef.deref();
      if (ref) {
        ref[prop] = value; // 绕过只读检查
        return true;
      }
      return false;
    }
  });
};
上述代码通过 WeakRef 创建对原对象的弱引用,确保不会阻止垃圾回收。代理对象在 set 拦截器中直接修改原始对象属性,从而规避语言层面的只读约束。
适用场景对比
场景是否适用说明
临时调试✅快速绕过限制,无需重构
生产环境❌可能破坏不可变性契约

第五章:综合选型建议与未来演进方向

企业级微服务架构中的技术栈权衡
在高并发场景下,服务网格与传统 API 网关的选型需结合团队运维能力。例如某金融平台在迁移至 Kubernetes 时,选择 Istio 配合自研策略控制器,通过以下配置实现细粒度流量控制:

apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
  name: payment-route
spec:
  hosts:
    - payment-service
  http:
    - route:
        - destination:
            host: payment-service
            subset: v1
          weight: 80
        - destination:
            host: payment-service
            subset: v2
          weight: 20
云原生环境下的可观测性建设
完整的监控体系应覆盖指标、日志与追踪三层。某电商平台采用如下技术组合提升故障排查效率:
  • Prometheus + Grafana 实现服务 SLA 实时可视化
  • OpenTelemetry 统一采集分布式追踪数据
  • Loki 轻量级日志聚合,降低存储成本 40%
技术演进路径规划
阶段目标架构关键技术
短期(0-6月)容器化+CI/CDDocker, Jenkins, Helm
中期(6-18月)服务网格化Istio, SPIFFE, OPA
长期(18月+)Serverless 平台Knative, Dapr, WASM
[ Dev Team ] --> [ GitLab CI ] --> [ ArgoCD ] --> [ K8s Cluster ] | | v v [ SonarQube ] [ Prometheus ]
基于ESP32-C3的物联网硬件设计:从免费工具链到PCB打样全流程实战 在物联网和嵌入式开发领域,硬件设计是连接软件逻辑与物理世界的关键环节。其核心原理在于通过电路设计将微控制器、传感器、通信模块等电子元件有机整合,实现特定功能。掌握硬件设计能力的技术价值在于能够自主实现产品原型,优化成本与性能,并深入理解系统底层运作。常见的应用场景包括智能家居节点、环境监测设备、工业传感终端等。本文以热门的ESP32-C3 RISC-V物联网芯片和广泛使用的KiCad免费EDA工具为例,详细解析了从核心器件选型、射频电路布局、PCB设计规则到Gerber文件生产的完整流程,并分享了在嘉立创平 阅读详情

相关推荐

SECS/GEM协议中的关键指令详解:从S1F1到S9F9的完整指南

本文详细解析了SECS/GEM协议中从S1F1到S9F9的关键指令,涵盖设备状态管理、控制诊断、报警处理等核心功能。通过实际案例和调试技巧,帮助开发者掌握半导体制造设备通信标准,解决SECS/GEM协议在实际工程应用中的通讯难题,提升生产线智能化水平。

weixin_26899659的博客 397

只读属性遇上序列化,PHP 8.3开发者必须掌握的5个技巧

掌握PHP 8.3只读属性的反射与序列化技巧,解决对象持久化难题。涵盖反射读取、序列化兼容处理、构造器验证等场景,提升代码安全性与稳定性。5个实用方法助力高效开发,值得收藏。

FastCompile的博客 842

C语言头文件完全解析(连“#”我都给你讲明白)

C语言头文件完全解析 引言 本文将尽量详细的介绍c语言的头文件所包含的知识,如有错误,还望指正。 萌新们肯定疑惑为什么每次打代码都要写一个所谓的头文件(如:#include<stdio.h>),这里先简单让大家有个了解,你所用的 printf("%d",a)就是这个 stdio里的东西,如果没有这个头文件,编译器都不知道 printf是个什么东东。所以头文件就是一个准备好的大仓库,你可...

CRAZY_eyes的博客 7万+

只读属性的反射陷阱与序列化突破,PHP 8.3你必须知道的5个技巧

掌握PHP 8.3只读属性的反射与序列化方案,解决对象序列化难题。涵盖反射读取只读属性、自定义序列化逻辑等5大实用技巧,适用于API开发与数据传输场景,提升代码稳定性与兼容性,值得收藏。

InstrIsle的博客 776

IBTrACS v04r01 数据提取实战:Pandas 筛选 JTWC/CMA/JMA 3机构最佳路径数据

本文详细介绍了如何使用 Pandas 高效提取和处理 IBTrACS v04r01 数据集中的最佳路径数据,特别针对 JTWC、CMA 和 JMA 三家权威机构的数据进行对比分析。通过构建可复用的数据提取函数,解决多机构数据质量差异问题,并提供高级分析与可视化应用示例,助力热带气旋研究。

clijovtbq401783153的博客 515

手把手教你用ObjectCRX进行Caxa二次开发:从零开始的环境搭建教程

本文是一份面向零基础初学者的Caxa二次开发实战指南,重点讲解如何使用ObjectCRX框架从零开始搭建开发环境。内容涵盖Visual Studio 2015版本锁定、ObjectCRX向导集成、项目创建、典型错误解决,并最终实现一个可在Caxa中运行的HelloWorld程序,帮助开发者快速入门并避开常见陷阱。

w3x4y的博客 509

PHP 8.3只读属性真的不可变吗?破解反射与序列化的安全边界

深入解析PHP 8.3只读属性的反射与序列化方案,揭示其并非绝对不可变的本质。探讨在对象序列化、依赖注入等场景下如何通过反射绕过只读限制,提供安全应对策略。掌握底层机制,规避潜在风险,值得收藏。

DebugLoom的博客 884

Java写项目前的准备工作指南(技术栈选择 环境搭建和工具配置 项目结构设计与模块划分)

在开始编写一个 Java 项目之前,做好充分的准备工作是至关重要的。很多初学者可能在没有清晰规划的情况下就开始编写代码,导致项目开发进度缓慢、结构混乱,甚至最终无法按预期完成。而事实上,项目的成功不仅仅取决于编码能力,还包括项目初期的规划和准备。准备工作是确保项目顺利进行的基础,它包括技术选型、环境搭建、需求分析、团队协作及项目管理等多个方面。通过这些准备,我们可以确保项目的开发不仅高效而且有可维护性,最终能交付出高质量的代码。在项目开发过程中,异常处理是非常关键的一部分。

eternal__day的博客 1188

PHP 8.3只读属性如何安全序列化?99%开发者忽略的关键细节

掌握PHP 8.3只读属性的反射与序列化方案,解决对象序列化时的只读属性异常问题。适用于API开发、缓存处理等场景,通过反射安全绕过只读限制,实现无缝序列化。方法可靠,兼容性强,值得收藏。

CompiWander的博客 578

NSGA-Ⅱ算法:从原理到实战,解锁多目标优化难题

本文深入解析NSGA-Ⅱ算法在多目标优化中的应用,从原理到实战全面覆盖。通过快速非支配排序、精英策略和拥挤度比较三大创新,NSGA-Ⅱ有效解决了传统算法的效率与多样性问题。结合工业案例展示其在注塑工艺优化中的显著效果,为工程师提供实用解决方案。

weixin_29207149的博客 366

添加odbc数据源时的一些问题和解决办法

pl/sql

Mr_Syh的博客 9642

揭秘PHP 8.3只读属性:如何安全实现反射访问与序列化处理

掌握PHP 8.3只读属性的反射与序列化方案,安全实现属性访问与数据持久化。适用于API开发、对象存储等场景,通过ReflectionClass安全读取只读属性,结合自定义序列化逻辑保障完整性。提升代码稳定性与兼容性,值得收藏。

ProceSeed的博客 610

实战案例四:Claude Code + Excel 技能处理表格数据

Excel 是商业世界中最通用的数据工具。无论是财务报表、销售数据还是项目计划,Excel 无处不在。本案例将展示如何利用 Claude Code 的 Excel 技能,自动化处理复杂的表格数据,告别繁琐的手工操作。

gaoxiang_120的专栏 475

PHP Period库版本升级指南:从3.0到5.0的完整迁移教程

PHP Period库是PHP中缺失的时间范围API,为开发者提供了强大的时间区间处理能力。从3.0版本到5.0版本的升级带来了许多重大改进,包括更好的类型安全性、更清晰的API设计以及性能优化。本指南将帮助您顺利完成从3.0到5.0的完整迁移过程。😊 ## 为什么需要升级到Period 5.0? Period 5.0版本带来了许多重要的改进,包括对PHP 8.1+的完全支持、更好的类型提示

gitblog_00721的博客 678

SAP B1中文培訓教材_SDK

公司内部培训资料,对开发工具 ,DIAPI, UIAPI,Add-ON有详细解说

华为的C语言编程规范.pdf

华为技术有限公司内部技术规范。本规范制定了编写C语言程序的基本原则、规则和建议。从代码的清晰、简洁、可测试、安全、程序效率、可移植各个方面对C语言编程作出了具体指导。

PgDog 可观测性实战:OTLP 推送 Prometheus 并在 Grafana 中可视化

PgDog(PostgreSQL connection pooler、load balancer 与 database sharder)内置了基于 OpenTelemetry 的指标推送能力,本指南以仓库中 `examples/grafana_prometheus` 完整示例为主线,讲解如何让 PgDog 以「推送(push)」方式把指标发送给 Prometheus,并通过 Grafana Pro

gitblog_01193的博客 828

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

Igbinary兼容性深度解析:PHP 5.2到8.0全版本支持

Igbinary作为PHP标准序列化器的高性能替代方案,从PHP 5.2到8.0+版本均提供全面支持,确保不同环境下的数据序列化稳定性与兼容性。本文将深入剖析其跨版本适配机制、关键特性支持及迁移注意事项,帮助开发者轻松应对PHP版本升级挑战。 ## 📊 PHP版本支持矩阵 Igbinary通过精细化的条件编译与API适配,实现了对PHP生态全版本的覆盖: - **基础支持**:PHP 5.

gitblog_01145的博客 428

深度学习工具包 DeepLearningToolbox

深度学习工具包Deprecation notice.-----This toolbox is outdated and no longer maintained.There are much better tools available for deep learning than this toolbox, e.g. [Theano](http://deeplearning.net/software/theano/), [torch](http://torch.ch/) or [tensorflow](http://www.tensorflow.org/)I would suggest you use one of the tools mentioned above rather than use this toolbox.Best, Rasmus.DeepLearnToolbox================A Matlab toolbox for Deep Learning.Deep Learning is a new subfield of machine learning that focuses on learning deep hierarchical models of data.It is inspired by the human brain&#39;s apparent deep (layered, hierarchical) architecture.A good overview of the theory of Deep Learning theory is[Learning Deep Architectures for AI](http://www.iro.umontreal.ca/~bengioy/papers/ftml_book.pdf)For a more informal introduction, see the following videos by Geoffrey Hinton and Andrew Ng.* [The Next Generation of Neural Networks](http://www.youtube.com/watch?v=AyzOUbkUf3M) (Hinton, 2007)* [Recent Developments in Deep Learning](http://www.youtube.com/watch?v=VdIURAu1-aU) (Hinton, 2010)* [Unsupervised Feature Learning and Deep Learning](http://www.youtube.com/watch?v=ZmNOAtZIgIk) (Ng, 2011)If you use this toolbox in your research please cite [Prediction as a candidate for learning deep hierarchical models of data](http://www2.imm.dtu.dk/pubdb/views/publication_details.php?id=6284)```@MASTERSTHESIS\{IMM2012-06284, author = "R. B. Palm", title = "Prediction as a candidate for learning deep hierarchical models of data", year = "2012",}```Contact: rasmusbergpalm at gmail dot comDirectories included in the toolbox-----------------------------------`NN/` - A library for Feedforward Backpropagation Neural Networks`CNN/` - A library for Convolutional Neural Networks`DBN/` - A library for Deep Belief Networks`SAE/` - A library for Stacked Auto-Encoders`CAE/` - A library for Convolutional Auto-Encoders`util/` - Utility functions used by the libraries`data/` - Data used by the examples`tests/` - unit tests to verify toolbox is workingFor references on each library check REFS.mdSetup-----1. Download.2. addpath(genpath(&#39;DeepLearnToolbox&#39;));Example: Deep Belief Network---------------------```matlabfunction test_example_DBNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit RBM and visualize its weightsrand(&#39;state&#39;,0)dbn.sizes = [100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);figure; visualize(dbn.rbm{1}.W&#39;); % Visualize the RBM weights%% ex2 train a 100-100 hidden unit DBN and use its weights to initialize a NNrand(&#39;state&#39;,0)%train dbndbn.sizes = [100 100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);%unfold dbn to nnnn = dbnunfoldtonn(dbn, 10);nn.activation_function = &#39;sigm&#39;;%train nnopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.10, &#39;Too big error&#39;);```Example: Stacked Auto-Encoders---------------------```matlabfunction test_example_SAEload mnist_uint8;train_x = double(train_x)/255;test_x = double(test_x)/255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit SDAE and use it to initialize a FFNN% Setup and train a stacked denoising autoencoder (SDAE)rand(&#39;state&#39;,0)sae = saesetup([784 100]);sae.ae{1}.activation_function = &#39;sigm&#39;;sae.ae{1}.learningRate = 1;sae.ae{1}.inputZeroMaskedFraction = 0.5;opts.numepochs = 1;opts.batchsize = 100;sae = saetrain(sae, train_x, opts);visualize(sae.ae{1}.W{1}(:,2:end)&#39;)% Use the SDAE to initialize a FFNNnn = nnsetup([784 100 10]);nn.activation_function = &#39;sigm&#39;;nn.learningRate = 1;nn.W{1} = sae.ae{1}.W{1};% Train the FFNNopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.16, &#39;Too big error&#39;);```Example: Convolutional Neural Nets---------------------```matlabfunction test_example_CNNload mnist_uint8;train_x = double(reshape(train_x&#39;,28,28,60000))/255;test_x = double(reshape(test_x&#39;,28,28,10000))/255;train_y = double(train_y&#39;);test_y = double(test_y&#39;);%% ex1 Train a 6c-2s-12c-2s Convolutional neural network %will run 1 epoch in about 200 second and get around 11% error. %With 100 epochs you&#39;ll get around 1.2% errorrand(&#39;state&#39;,0)cnn.layers = { struct(&#39;type&#39;, &#39;i&#39;) %input layer struct(&#39;type&#39;, &#39;c&#39;, &#39;outputmaps&#39;, 6, &#39;kernelsize&#39;, 5) %convolution layer struct(&#39;type&#39;, &#39;s&#39;, &#39;scale&#39;, 2) %sub sampling layer struct(&#39;type&#39;, &#39;c&#39;, &#39;outputmaps&#39;, 12, &#39;kernelsize&#39;, 5) %convolution layer struct(&#39;type&#39;, &#39;s&#39;, &#39;scale&#39;, 2) %subsampling layer};cnn = cnnsetup(cnn, train_x, train_y);opts.alpha = 1;opts.batchsize = 50;opts.numepochs = 1;cnn = cnntrain(cnn, train_x, train_y, opts);[er, bad] = cnntest(cnn, test_x, test_y);%plot mean squared errorfigure; plot(cnn.rL);assert(er<0.12, &#39;Too big error&#39;);```Example: Neural Networks---------------------```matlabfunction test_example_NNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);% normalize[train_x, mu, sigma] = zscore(train_x);test_x = normalize(test_x, mu, sigma);%% ex1 vanilla neural netrand(&#39;state&#39;,0)nn = nnsetup([784 100 10]);opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samples[nn, L] = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.08, &#39;Too big error&#39;);%% ex2 neural net with L2 weight decayrand(&#39;state&#39;,0)nn = nnsetup([784 100 10]);nn.weightPenaltyL2 = 1e-4; % L2 weight decayopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, &#39;Too big error&#39;);%% ex3 neural net with dropoutrand(&#39;state&#39;,0)nn = nnsetup([784 100 10]);nn.dropoutFraction = 0.5; % Dropout fraction opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, &#39;Too big error&#39;);%% ex4 neural net with sigmoid activation functionrand(&#39;state&#39;,0)nn = nnsetup([784 100 10]);nn.activation_function = &#39;sigm&#39;; % Sigmoid activation functionnn.learningRate = 1; % Sigm require a lower learning rateopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, &#39;Too big error&#39;);%% ex5 plotting functionalityrand(&#39;state&#39;,0)nn = nnsetup([784 20 10]);opts.numepochs = 5; % Number of full sweeps through datann.output = &#39;softmax&#39;; % use softmax outputopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, &#39;Too big error&#39;);%% ex6 neural net with sigmoid activation and plotting of validation and training error% split training data into training and validation datavx = train_x(1:10000,:);tx = train_x(10001:end,:);vy = train_y(1:10000,:);ty = train_y(10001:end,:);rand(&#39;state&#39;,0)nn = nnsetup([784 20 10]); nn.output = &#39;softmax&#39;; % use softmax outputopts.numepochs = 5; % Number of full sweeps through dataopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, tx, ty, opts, vx, vy); % nntrain takes validation set as last two arguments (optionally)[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, &#39;Too big error&#39;);```[![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/rasmusbergpalm/deeplearntoolbox/trend.png)](https://bitdeli.com/free "Bitdeli Badge")

PHP 属性访问控制不足详解与解决方案

本文详细介绍了PHP属性访问控制不足的问题及解决方案。首先分析了三类常见问题:无意的属性暴露、属性访问逃逸和继承导致的访问控制削弱。然后提出了两种基础解决方案:使用标准的Getter/Setter方法实现可控访问,以及只读属性模式确保数据不可变性。最后介绍了通过魔术方法__get和__set实现更灵活的访问控制,包括属性白名单、一次性写入属性等机制。这些方案可有效防止敏感数据暴露、确保数据完整性并实现精细化的访问控制。

深山技术宅的博客 833

PHP 8.2 readonly class避坑指南,90%新手忽略的5个关键细节

掌握PHP 8.2只读类(readonly class)关键细节,避免常见错误。详解适用场景、属性定义规范、嵌套对象处理、性能优势及与构造函数协同使用技巧。提升代码安全性与可维护性,90%新手忽略的坑全解析,值得收藏。

BytePerch的博客 637

PHP 8.1.0 正式发布

????????关注后回复“进群”,拉你进程序员交流群????????文| 御坂弟弟出品 | OSC开源社区(ID:oschina2013)PHP 8.1.0 现已发布,该版本带来了许多改进和新功能。枚举使...

<sdffdsfsdfdfs>sfsfsfsdfsdffds</sdfsDS>Fsd 243

phar-io/manifest与PHP 8.3兼容性测试报告

phar-io/manifest作为读取PHP Archive (PHAR)中manifest信息的核心组件,其与最新PHP版本的兼容性直接影响依赖项目的稳定性。本测试基于[composer.json](https://link.gitcode.com/i/7812814b1f116fccc1c72f4ea5f4982c)中声明的PHP版本约束`^7.2 || ^8.0`,在PHP 8.3.0环境...

gitblog_00961的博客 914

【PHP 8.2只读类深度解析】:掌握readonly class的5大核心优势与实战应用场景

掌握PHP 8.2只读类(readonly class)核心用法,解决对象状态不可变需求。涵盖属性只读、性能优化、代码安全等5大优势,适用于DTO、配置对象等场景。提升代码健壮性与可维护性,值得收藏。

IterLoom的博客 675

PHP 值对象比较困难详解与解决方案

PHP值对象比较的难点与解决方案 摘要:PHP中值对象比较存在固有困难,主要由于PHP的对象引用机制与值对象理念冲突。默认的==和===操作符无法满足值对象基于属性值的逻辑相等需求。本文提出三种解决方案:(1)显式实现equals()方法确保属性比较;(2)使用Trait复用比较逻辑;(3)采用属性白名单机制。高级场景中还需处理嵌套对象和集合比较问题。这些方案能有效解决PHP值对象比较的痛点,确保符合领域驱动设计原则。

深山技术宅的博客 1058

【PHP 8.4性能革命】:对比PHP 7.4/8.0/8.1/8.2/8.3,性能提升究竟有多猛?

想了解php 8.4 性能对比旧版本提升多少?本文实测对比PHP 7.4至8.3各版本在Web请求、并发处理与内存占用等场景下的表现,揭示JIT优化与新特性带来的核心性能飞跃。数据详实,方法清晰,值得收藏

InstrFun的博客 403

任意只读文件漏洞分析

官方Session定义:在计算机中,尤其是在网络应用中,称为“会话控制”。Session对象存储特定用户会话所需的属性及配置信息。session保存的位置是在服务器端session通常是要配合cookie使用因为HTTP的无状态性,服务端产生了session来标识当前的用户状态本质上,session就是一种可以维持服务器端的数据存储技术。即**session技术就是一种基于后端有别于数据库的临时存储数据的技术**

m0_61869253的博客 1661

PHP 8.7新特性全面评测(性能测试数据首次公开)

深入解析PHP 8.7新特性性能测试,揭示最新版本在高并发与Web服务中的实际表现。通过真实场景压测数据对比,展示启动速度、内存优化与执行效率提升。全面评测JIT改进与类型系统增强带来的性能飞跃,为升级决策提供依据,值得收藏。

BytePerch的博客 1089

php 8.4 有什么新特性?

功能:引入了新的多字节字符串处理函数,如 mb_ucfirst()、mb_lcfirst()、mb_trim() 等,确保对多字节字符串正确执行裁剪和更改大小写等操作。功能:允许开发者独立控制属性的读写权限,即一个属性可以是只读的或只写的,而不需要额外的 getter 和 setter 方法。功能:引入了新的数组函数,如 array_find() 和 array_find_key(),简化了常见的数组操作。功能:引入了惰性对象,允许开发者创建具有延迟初始化的对象,从而降低资源使用,提高性能。

rock365的博客 849
上一篇: 还在用纯C#做加密?掌握Rust DLL集成技术,性能立竿见影!
下一篇: PostGIS数据如何直连R?你不可错过的10个sf 1.1操作秘诀
DebugVibe
博客等级 码龄1年 151粉丝 2172原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值