讲师中心 微信公众号
AI工具推荐 视频效率加速

PHP:区分对象的声明属性与动态属性

夜敏酱_7837

夜敏酱_7837

发布时间:2025-11-14 13:44:02

|

478人浏览过

|

来源于php中文网

原创

php:区分对象的声明属性与动态属性

本文详细介绍了在PHP中如何程序化地区分对象的声明属性和动态属性。通过利用get_class_vars()获取类的默认声明属性和get_object_vars()获取对象的所有实例属性,再结合array_diff_key()函数,我们可以高效地识别出在运行时动态添加的属性,从而增强代码的健壮性和可维护性。

在PHP的面向对象编程中,对象可以拥有两种类型的属性:一种是在类定义中明确声明的属性,另一种是在对象实例化后动态添加的属性。理解并能够程序化地区分这两种属性对于调试、序列化或进行高级对象操作至关重要。

声明属性与动态属性的本质区别

  • 声明属性(Declared Properties):这些属性在类的定义中通过public, protected, private等关键字明确指定。它们是类蓝图的一部分,所有该类的实例都将拥有这些属性(尽管值可能不同)。
  • 动态属性(Dynamic Properties):这些属性不在类的定义中,而是在对象创建后,通过直接赋值的方式在运行时添加到特定的对象实例上。它们是该对象独有的,不影响其他同类实例。

例如:

class Foo {
   public $bar; // 声明属性
}

$obj = new Foo;
$obj->baz = 1; // 动态属性

在上述代码中,$bar是Foo类的一个声明属性,而$baz是$obj实例的一个动态属性。

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

识别动态属性的解决方案

PHP提供了一系列内置的反射函数,可以帮助我们检查类和对象的结构。结合这些函数,我们可以设计一个简单而有效的方法来区分声明属性和动态属性。

核心思路是:

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

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

下载
  1. 获取类中所有声明的(公共)属性。
  2. 获取对象实例中所有当前的(可访问的)属性。
  3. 通过比较这两组属性的键,找出那些存在于对象实例中但未在类中声明的属性,它们就是动态属性。

步骤一:获取声明的类属性

使用get_class_vars()函数可以获取一个类的所有默认公共属性。为了使代码更具通用性,我们可以结合get_class()函数来动态获取对象的类名。

// 假设 $obj 是一个对象实例
$className = get_class($obj);
$declaredProperties = get_class_vars($className);

// $declaredProperties 将包含所有公共声明属性的名称及其默认值

步骤二:获取对象的所有实例属性

get_object_vars()函数可以获取一个对象实例的所有可访问属性。如果从外部作用域调用,它将返回所有公共属性。如果从对象内部调用,它将返回所有公共、受保护和私有属性。

// 假设 $obj 是一个对象实例
$allObjectProperties = get_object_vars($obj);

// $allObjectProperties 将包含对象实例上所有可访问属性的名称和当前值

步骤三:识别动态属性

通过比较$allObjectProperties和$declaredProperties的键,我们可以找出动态属性。array_diff_key()函数正是为此目的而设计的,它返回第一个数组中存在但不在第二个数组中存在的键值对。

$dynamicProperties = array_diff_key($allObjectProperties, $declaredProperties);

// $dynamicProperties 将只包含动态添加的属性及其当前值

完整示例代码

将上述步骤整合到一起,我们可以构建一个完整的示例:

<?php

class Foo {
   public $bar; // 声明的公共属性
   protected $protectedProp = 'protected_value'; // 声明的受保护属性
   private $privateProp = 'private_value'; // 声明的私有属性

   public function __construct() {
       $this->bar = 'default_bar';
   }

   public function getAllInternalProperties() {
       return get_object_vars($this);
   }
}

// 实例化对象并添加动态属性
$obj = new Foo;
$obj->baz = 1; // 动态公共属性
$obj->qux = 'hello world'; // 另一个动态公共属性

echo "--- 原始对象结构 ---\n";
print_r($obj);

// 1. 获取类的公共声明属性
// 注意:get_class_vars() 仅返回公共声明属性
$declaredProperties = get_class_vars(get_class($obj));
echo "\n--- 声明的公共属性 (get_class_vars) ---\n";
print_r($declaredProperties);

// 2. 获取对象实例的所有可访问属性 (从外部作用域调用,仅返回公共属性)
$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);

echo "\n--- 从对象内部获取所有属性 (包括protected/private) ---\n";
// 为了演示 get_object_vars 在内部作用域的行为
$allInternalProperties = $obj->getAllInternalProperties();
print_r($allInternalProperties);

?>

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

--- 原始对象结构 ---
Foo Object
(
    [bar] => default_bar
    [protectedProp:protected] => protected_value
    [privateProp:private] => private_value
    [baz] => 1
    [qux] => hello world
)

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

--- 对象所有可访问属性 (get_object_vars) ---
Array
(
    [bar] => default_bar
    [baz] => 1
    [qux] => hello world
)

--- 识别出的动态属性 ---
Array
(
    [baz] => 1
    [qux] => hello world
)

--- 从对象内部获取所有属性 (包括protected/private) ---
Array
(
    [bar] => default_bar
    [protectedProp] => protected_value
    [privateProp] => private_value
    [baz] => 1
    [qux] => hello world
)

从输出可以看出:

  • get_class_vars()只返回了$bar,因为它是唯一的公共声明属性。
  • get_object_vars()从外部作用域调用时,返回了$bar, $baz, $qux,即所有公共属性(无论是声明的还是动态的)。
  • array_diff_key()成功地从$allObjectProperties中排除了$declaredProperties的键,从而准确识别出了$baz和$qux这两个动态属性。
  • 从对象内部调用get_object_vars() (getAllInternalProperties方法) 可以获取到所有声明的属性,包括protected和private,以及动态属性。

注意事项与总结

  1. 可见性限制:
    • get_class_vars()函数只会返回类的公共(public)声明属性。
    • get_object_vars()函数在从类外部调用时,也只会返回对象的公共(public)属性(无论是声明的还是动态的)。
    • 因此,本教程提供的方法主要用于识别公共动态属性,并将其与公共声明属性区分开来。
  2. 全面性:如果需要获取包括protected和private在内的所有声明属性,或者需要更深入的属性元数据(如是否为静态、默认值等),则应考虑使用PHP的Reflection API(例如ReflectionClass::getProperties())。然而,对于大多数仅关注公共属性的场景,上述方法已经足够简洁高效。
  3. 性能:这些内置函数通常经过高度优化,在大多数应用中,其性能开销可以忽略不计。

通过上述方法,开发者可以清晰地识别出PHP对象中的动态属性,这在需要对对象进行精确控制、避免意外属性、或者在特定场景下(如魔术方法__get, __set的实现)区分属性来源时非常有用。

热门AI工具

更多
Lovart
Lovart Hot

一款面向视觉设计创作的AI设计平台,可通过智能体和画布工作流辅助制作海报、Logo、网页、PPT及其他视觉内容。

DeepSeek

DeepSeek是一款面向对话、写作、编程和推理场景的AI大模型工具。

音述AI
音述AI Hot

一款AI音频处理工具,主要用于音述AI是一个以“用声音述说故事”为核心的 AI 音乐创作与声音分享社区,适合需要提升相关任务效率的用户。

切问学术

切问学术是一款AI论文写作工具,复旦大学NLP团队推出的AI学术智能体。

PixTV
PixTV Hot

PixTV是一款面向AIGC内容创作的AI视频生成工具。

火山引擎

火山引擎是一款面向企业的云计算与AI服务平台。

豆包大模型

豆包大模型是一款由字节跳动推出的企业级大语言模型服务平台。

WorkBuddy

一款AI办公效率工具,主要用于腾讯云推出的AI原生桌面智能体工作台,适合需要提升相关任务效率的用户。

讯飞智作

讯飞智作是一款AI视频创作工具,AI文本配音工具,数字人课程、营销视频制作。

相关专题

更多
go语言 面向对象
go语言 面向对象

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

6235

2025.09.05

java面向对象
java面向对象

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

322

2025.11.27

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

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

344

2026.04.09

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

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

223

2026.04.17

Linux 新手先学哪些命令
Linux 新手先学哪些命令

Linux新手命令专题汇集终端基础、文件目录操作、文本查看、软件安装和权限管理等入门文章,帮助按实际任务练习常用命令并建立命令行操作习惯。

0

2026.10.15

MySQL 忘记密码怎么办
MySQL 忘记密码怎么办

MySQL忘记密码专题汇集不同版本与系统下的root密码重置方法,覆盖MySQL 5.7、8.0、Mac、Linux及本地集成环境,并提示恢复权限与重新登录的检查步骤。

0

2026.10.15

Vue.js 中 ref 和 reactive 的区别
Vue.js 中 ref 和 reactive 的区别

Vue.js中ref和reactive的区别专题汇集两种响应式API的定义、访问方式、对象解构、侦听与性能取舍等文章,帮助结合实际状态类型选择合适写法。

0

2026.10.15

VS Code 怎么配置开发环境
VS Code 怎么配置开发环境

VS Code开发环境专题汇集编辑器安装、语言扩展、编译器、解释器、终端和调试配置文章,覆盖Java、Python、C++和PHP等常见语言的入门设置。

0

2026.10.15

C++ 开发环境怎么搭建
C++ 开发环境怎么搭建

C++开发环境专题汇集Windows、Linux下的编译器与IDE安装配置教程,涵盖GCC、Clang、Visual Studio、CLion和VS Code,以及编译运行首个程序的步骤。

0

2026.10.15

热门下载

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

精品课程

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

共0课时 | 0人学习

MyEclipse学习中心
MyEclipse学习中心

共0课时 | 0人学习

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

共0课时 | 0人学习

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

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn