当前位置: 首页 > news >正文

PHP反射机制核心应用

PHP反射机制核心应用

反射是PHP中强大的工具,可以在运行时获取类、方法、属性的信息。框架的依赖注入容器、路由系统、自动文档生成都依赖于反射。今天说说反射的各种用法。

反射API的核心类有ReflectionClass、ReflectionMethod、ReflectionProperty、ReflectionParameter等。

```php
class User
{
private int $id;
public string $name;
protected string $email;
private ?string $phone = null;
public const MAX_LOGIN_ATTEMPTS = 5;

public function __construct(string $name, string $email)
{
$this->name = $name;
$this->email = $email;
}

public function getName(): string
{
return $this->name;
}

private function validateEmail(): bool
{
return filter_var($this->email, FILTER_VALIDATE_EMAIL) !== false;
}

public static function createFromArray(array $data): self
{
return new self($data['name'], $data['email']);
}
}

// 反射类
$ref = new ReflectionClass(User::class);

echo "类名: " . $ref->getName() . "\n";
echo "文件名: " . $ref->getFileName() . "\n";
echo "是否可实例化: " . ($ref->isInstantiable() ? '是' : '否') . "\n";
echo "父类: " . ($ref->getParentClass() ? $ref->getParentClass()->getName() : '无') . "\n";

// 获取属性
echo "\n属性:\n";
foreach ($ref->getProperties() as $prop) {
$modifiers = Reflection::getModifierNames($prop->getModifiers());
echo " " . implode(' ', $modifiers) . " \${$prop->getName()}\n";
}

// 获取方法
echo "\n方法:\n";
foreach ($ref->getMethods() as $method) {
$modifiers = Reflection::getModifierNames($method->getModifiers());
echo " " . implode(' ', $modifiers) . " {$method->getName()}()\n";
}

// 获取常量
echo "\n常量:\n";
foreach ($ref->getConstants() as $name => $value) {
echo " {$name} = {$value}\n";
}
?>
```

反射用于自动创建对象和调用方法:

```php
// 自动依赖解析
class Container
{
public function make(string $class): object
{
$ref = new ReflectionClass($class);
$constructor = $ref->getConstructor();

if ($constructor === null) {
return $ref->newInstance();
}

$params = [];
foreach ($constructor->getParameters() as $param) {
$type = $param->getType();
if ($type instanceof ReflectionNamedType && !$type->isBuiltin()) {
$params[] = $this->make($type->getName());
} elseif ($param->isDefaultValueAvailable()) {
$params[] = $param->getDefaultValue();
} else {
throw new RuntimeException("无法解析: {$param->getName()}");
}
}

return $ref->newInstanceArgs($params);
}

public function callMethod(object $object, string $method, array $args = []): mixed
{
$ref = new ReflectionMethod($object, $method);
$params = [];

foreach ($ref->getParameters() as $param) {
$name = $param->getName();
if (isset($args[$name])) {
$params[] = $args[$name];
} elseif ($param->getType() && !$param->getType()->isBuiltin()) {
$params[] = $this->make($param->getType()->getName());
} elseif ($param->isDefaultValueAvailable()) {
$params[] = $param->getDefaultValue();
} else {
throw new RuntimeException("无法解析参数: $name");
}
}

return $ref->invokeArgs($object, $params);
}
}

class Logger
{
public function log(string $message): void
{
echo "日志: $message\n";
}
}

class UserService
{
public function __construct(
private Logger $logger
) {}

public function register(string $name, string $email, Logger $logger = null): void
{
$logger = $logger ?? $this->logger;
$logger->log("用户注册: $name ($email)");
}
}

$container = new Container();
$service = $container->make(UserService::class);
$container->callMethod($service, 'register', ['name' => '张三', 'email' => 'z@test.com']);
?>
```

反射在属性访问控制上的应用:

```php
class Entity
{
private int $id = 0;
private string $createdAt = '';
private string $updatedAt = '';

public function getId(): int
{
return $this->id;
}
}

function objectToArray(object $obj): array
{
$ref = new ReflectionClass($obj);
$result = [];

foreach ($ref->getProperties() as $prop) {
$prop->setAccessible(true);
$result[$prop->getName()] = $prop->getValue($obj);
}

return $result;
}

function arrayToObject(array $data, string $className): object
{
$ref = new ReflectionClass($className);
$obj = $ref->newInstanceWithoutConstructor();

foreach ($data as $name => $value) {
if ($ref->hasProperty($name)) {
$prop = $ref->getProperty($name);
$prop->setAccessible(true);
$prop->setValue($obj, $value);
}
}

return $obj;
}

$entity = new Entity();
print_r(objectToArray($entity));
?>
```

反射是PHP框架的核心技术。容器自动解析依赖、路由将URL映射到控制器方法、ORM将数据库记录映射到对象,背后都是反射在起作用。理解反射的用法,对理解框架原理很有帮助。

http://www.jsqmd.com/news/945282/

相关文章:

  • G-Helper深度评测:华硕笔记本轻量级控制工具的技术解析与性能对比
  • 环境配置与基础教程:代码与数据版本联动:用 DVC + Git 联动管理代码、数据与模型,实现一键回滚实验
  • 一劳永逸解决IDM激活难题:开源脚本的智能解决方案
  • R-2R梯形电阻DAC的‘隐形杀手’:除了电阻精度,这些细节同样致命(附STM32代码优化方案)
  • 2026 宜昌卫生间漏水、外墙、楼顶、地下室、阳光房渗漏维修师傅推荐|同城附近上门防水补漏公司测评 - 防水百科
  • AVR单片机实现1024点FFT频谱分析:从傅里叶变换到嵌入式实践
  • 避坑指南:Ubuntu 22.04 on Jetson Orin Nano配置虚拟显示器,解决VNC黑屏/只有Logo
  • Redis 过期删除策略和内存淘汰策略?
  • STM32F103RBT6全双工语音对讲硬件套件:含AD原理图PCB、3D封装库与Speex实时编解码固件
  • DIY低成本物联网水井监测仪:基于Particle与ThingSpeak的水位水温电导率实时监测方案
  • 环境配置与基础教程:面试必考速记:手写一个极简的 PyTorch 训练引擎,彻底理解 forward/backward/optimizer 调用链
  • 从零打造语音控制智能魔杖:Bolt IoT与IFTTT实战指南
  • Office即点即用和传统安装到底啥区别?手把手教你用ODT工具管理所有版本
  • 从电磁炉到氮化镓快充:反激(FLYBACK)拓扑的‘跨界’生存指南与选型要点
  • 别再死记硬背公式了!手把手带你用Simulink复现汽车悬架7自由度模型(含参数设置避坑点)
  • 总经理的咒语:驱动业务孵化的核心管理哲学与系统方法论
  • 26届秋招必刷:手写YOLO数据集自动划分脚本,支持VOC/COCO互转与漏标检测
  • 微软研究院七大前沿技术解析:从人机交互到科学探索的创新实践
  • 别再只会conda info --envs了!这5个隐藏技巧帮你高效管理Python虚拟环境
  • AI工具如何重构智能运维体系:3个已被验证的架构升级路径
  • WebRTC录制视频没时间轴?手把手教你用fix-webm-duration.js解决并保存为MP4
  • 从BIOS到路由器:深入拆解SPI NOR Flash的硬件连接与‘芯片内执行’(XIP)奥秘
  • 从零构建企业研究实验室:定位、人才、流程与避坑指南
  • 保姆级教程:在Dell OptiPlex 7080/5090/300上搞定CentOS 7.5 UEFI安装(含网卡驱动避坑)
  • 为什么你的Copilot总在智能音箱里“失语”?——AI工具协议栈错配的4层根因分析
  • 免费开源图片去重神器:3步告别重复照片困扰,释放存储空间
  • Mamba模型环境搭建:为什么你的causal-conv1d在Windows上装不上?
  • 基于 OpenCV 的校园课堂行为识别与智能考勤分析系统实战
  • 手把手调试:在Ubuntu 22.04上实战跟踪bnxt_re驱动的QP/CQ工作流
  • 生产级落地数据洗理:FiftyOne 1.20 可视化排查YOLO标注噪声,涨点3%的秘密武器