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将数据库记录映射到对象,背后都是反射在起作用。理解反射的用法,对理解框架原理很有帮助。
