PHP中区分对象声明属性与动态属性的方法

轻静大大_9501

轻静大大_9501

2025-11-09

969人浏览

原创

PHP中区分对象声明属性与动态属性的方法

本文详细介绍了在php中如何通过编程方式区分对象的已声明属性(在类定义中明确指定)和动态属性(在对象实例化后添加)。我们将利用`get_class_vars()`和`get_object_vars()`函数,结合数组操作,高效识别并分离这两种属性类型,为代码分析和调试提供便利。

在PHP面向对象编程中,对象的属性可以分为两种主要类型:声明属性(Declared Properties)和动态属性(Dynamic Properties)。声明属性是在类定义中明确定义的,它们是类结构的一部分。而动态属性则是在对象实例化之后,在运行时动态添加到对象上的,它们并不在类的原始定义中。理解并能够区分这两种属性对于代码分析、调试以及某些高级反射操作至关重要。

区分声明属性与动态属性的挑战

考虑以下PHP代码示例:

class Foo {
   public $bar; // 这是一个声明属性
}

$obj = new Foo;
$obj->baz = 1; // 这是一个动态属性

在此示例中,$bar是Foo类的一个声明属性,而$baz是在$obj实例上动态创建的属性。我们如何通过编程方式识别出$bar是声明属性,而$baz是动态属性呢?

解决方案:利用PHP内置函数

PHP提供了两个核心函数,它们是解决这个问题的关键:

  1. get_class_vars(string $class_name): 此函数返回由类$class_name声明的所有静态属性的默认值。对于非静态属性,它返回其在类定义中的默认值(如果没有默认值则为null)。重要的是,它只返回在类定义中明确声明的属性。
  2. get_object_vars(object $object): 此函数返回由对象$object的所有可访问属性组成的关联数组。这包括所有声明属性(无论其可见性如何,只要当前作用域可访问)以及所有动态属性。

通过结合使用这两个函数,我们可以计算出声明属性和动态属性的差异。

btpanel phpsite 宝塔面板PHP网站
btpanel phpsite 宝塔面板PHP网站

宝塔面板 PHP 网站管理:站点创建、删除、启停、PHP 版本切换、域名管理、SSL证书管理、伪静态管理、数据库管理

下载

实现步骤

  1. 获取类声明的属性:使用get_class_vars()函数获取指定类中所有声明的属性。
  2. 获取对象的所有属性:使用get_object_vars()函数获取特定对象实例上的所有属性,包括声明属性和动态属性。
  3. 计算差异:将第二步得到的所有属性与第一步得到的声明属性进行比较,其差集即为动态属性。

示例代码

下面是具体的实现代码:

<?php class Foo {
   public $bar; // 声明属性
   protected $declaredProtected = 'protected_value'; // 声明属性
   private $declaredPrivate = 'private_value'; // 声明属性
}

$obj = new Foo;
$obj->baz = 1; // 动态属性
$obj->dynamicProperty = 'hello'; // 另一个动态属性

// 1. 获取类声明的属性
// 注意:get_class_vars() 只能获取 public 属性的默认值,
// 或者在类内部调用时获取所有可见属性的默认值。
// 对于本例,我们主要关心其键名。
$declaredProperties = get_class_vars(get_class($obj));

echo "--- 声明属性 (get_class_vars) ---\n";
print_r($declaredProperties);

// 2. 获取对象的所有属性 (包括声明属性和动态属性)
// get_object_vars() 在当前作用域下,会返回所有可访问的属性。
// 如果在类外部调用,它通常只返回 public 属性。
// 但其键名仍然包含了所有声明的 public 属性。
$allObjectProperties = get_object_vars($obj);

echo "\n--- 对象所有属性 (get_object_vars) ---\n";
print_r($allObjectProperties);

// 3. 计算动态属性
// 通过比较两个数组的键名差异,我们可以识别出动态属性。
$dynamicProperties = array_diff_key($allObjectProperties, $declaredProperties);

echo "\n--- 动态属性 ---\n";
print_r($dynamicProperties);

?>

输出结果分析

运行上述代码,你将得到类似以下的输出:

--- 声明属性 (get_class_vars) ---
Array
(
    [bar] => 
)

--- 对象所有属性 (get_object_vars) ---
Array
(
    [bar] => 
    [baz] => 1
    [dynamicProperty] => hello
)

--- 动态属性 ---
Array
(
    [baz] => 1
    [dynamicProperty] => hello
)

解释:

  • get_class_vars(get_class($obj)) 返回了一个数组,其中包含Foo类中声明的public属性$bar。请注意,它不包含protected或private属性,因为get_class_vars()在类外部只能访问public属性的默认值。然而,对于识别键名来说,这已经足够了。
  • get_object_vars($obj) 返回了对象$obj上所有可访问的属性,包括声明的$bar以及动态添加的$baz和$dynamicProperty。
  • array_diff_key($allObjectProperties, $declaredProperties) 函数比较了两个数组的键名,并返回在$allObjectProperties中存在但在$declaredProperties中不存在的键及其对应的值。这正是我们所寻找的动态属性。

注意事项

  • get_class() 的使用:在get_class_vars()函数中,我们使用了get_class($obj)而不是直接硬编码类名'Foo'。这样做的好处是使代码更具通用性。无论$obj是哪个类的实例,get_class()都会动态获取其类名,从而确保get_class_vars()始终作用于正确的类定义。
  • 可见性限制:get_class_vars()和get_object_vars()在类外部调用时,通常只能访问public属性。如果需要在类内部或通过反射来获取所有可见性(包括protected和private)的属性,情况会更复杂,可能需要使用PHP的反射API(ReflectionClass和ReflectionProperty)。然而,对于区分声明的public属性和动态属性,上述方法是有效且简洁的。
  • 默认值:get_class_vars()返回的是类声明属性的默认值。如果属性没有显式设置默认值,则其值为null。这不影响我们通过键名来识别属性的目的。

总结

通过巧妙地结合使用get_class_vars()和get_object_vars()这两个PHP内置函数,我们可以高效且准确地识别出对象中的动态属性。这种方法对于需要对对象结构进行运行时分析、调试或实现特定功能(如序列化、ORM等)的场景非常有用。理解PHP中属性的生命周期和可见性规则是掌握这一技巧的基础。

php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!

相关文章

PHP速学教程(入门到精通)
PHP速学教程(入门到精通)

PHP怎么学习?PHP怎么入门?PHP在哪学?PHP怎么学才快?不用担心,这里为大家提供了PHP速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

下载

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

相关专题

更多
string转int
string转int

在编程中,我们经常会遇到需要将字符串(str)转换为整数(int)的情况。这可能是因为我们需要对字符串进行数值计算,或者需要将用户输入的字符串转换为整数进行处理。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

2023.08.02

6899

3

c语言中null和NULL的区别
c语言中null和NULL的区别

c语言中null和NULL的区别是:null是C语言中的一个宏定义,通常用来表示一个空指针,可以用于初始化指针变量,或者在条件语句中判断指针是否为空;NULL是C语言中的一个预定义常量,通常用来表示一个空值,用于表示一个空的指针、空的指针数组或者空的结构体指针。

2023.09.22

549

3

java中null的用法
java中null的用法

在Java中,null表示一个引用类型的变量不指向任何对象。可以将null赋值给任何引用类型的变量,包括类、接口、数组、字符串等。想了解更多null的相关内容,可以阅读本专题下面的文章。

2024.03.01

1698

6

go语言 面向对象
go语言 面向对象

本专题整合了go语言面向对象相关内容,阅读专题下面的文章了解更多详细内容。

2025.09.05

7095

14

java面向对象
java面向对象

本专题整合了java面向对象相关内容,阅读专题下面的文章了解更多详细内容。

2025.11.27

362

13

C++ 面向对象编程与设计模式实践
C++ 面向对象编程与设计模式实践

本专题整合了 C++ 面向对象编程的核心机制,涵盖类的定义与访问控制、构造函数与析构函数、拷贝语义与移动语义、继承与虚函数多态、抽象类与接口、运算符重载、友元函数等关键知识点,同时结合单例模式、工厂模式、观察者模式、策略模式等常用设计模式的 C++ 实现,帮助开发者写出结构清晰、易于维护的面向对象代码。

2026.04.09

364

30

Java 面向对象与核心编程机制
Java 面向对象与核心编程机制

系统讲解 Java 面向对象编程的核心知识体系,涵盖类的定义与封装、构造方法与 this/super 关键字、继承与方法重写、多态与向上向下转型、抽象类与接口的区别与设计原则、异常处理机制(try-catch-finally / 自定义异常)、泛型的类型参数与通配符、集合框架(List/Set/Map)的使用与遍历方式,帮助开发者全面掌握 Java 程序设计的核心机制与面向对象思维。

2026.04.17

243

15

Vite 项目如何打包和部署
Vite 项目如何打包和部署

Vite项目打包部署专题汇集生产构建、产物预览、输出目录、资源路径、Nginx与GitHub Pages部署及常见白屏和路由404问题的已审核文章,帮助读者完成上线流程。

2026.10.28

60

16

Vite 如何搭配 Vue.js
Vite 如何搭配 Vue.js

Vite搭配Vue.js专题汇集创建Vue 3项目、配置开发环境、路径别名、Vue插件、代理、多环境构建与调试的已审核文章,帮助读者完成从初始化到日常开发的配置。

2026.10.28

40

15

热门下载

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

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
墨刀帮助中心
墨刀帮助中心

共0课时 | 0人学习

MyEclipse学习中心
MyEclipse学习中心

共0课时 | 0人学习

Apache Subversion 官方手册
Apache Subversion 官方手册

共0课时 | 0人学习