Еще в ноябре 2005 года на встрече в Париже разработчики обсудили новые возможности следующей, шестой, версии PHP. Интересует ли Вас, какой будет эта версия? Примите участие в опросе, который проводится на сайте рассылки.
[опрос на английском языке: PHP 6: Are you interesting in? (PHP 6: Вы зантересованы?) - YES (ДА) - NO (НЕТ)]
PHP 5: Новые возможности.
Рефлексия
The Pterodactyl
Copyright 2006 Pterodactyl's School
Copyright 2006 Pterodactyl's School.
Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.2 or any later version published by the Free Software Foundation; with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts. A copy of the license is included in the section entitled "GNU Free Documentation License".
28.04.2006
История переиздания
Издание 1.00
[ Дата ]
Первоначальная версия.
Аннотация
Доступ к программным объектам скрипта во время его исполнения при помощи рефлексии; API. Шаблон делегирования.
PHP и раньше обеспечивал возможность доступа к некоторым программным объектам во время исполнения скрипта при помощи переменных (например, вызов функций или создание классов с помощью оператора new). Однако, PHP 5 предоставляет действительно полноценный и гибкий механизм такого доступа, который называется рефлексией (reflection),
или интроспекцией (introspection).
Замечание
Строго говоря, такой механизм предоставляет не сам PHP 5, а движок, на котором он работает, - Zend Engine [1].
API
Доступ к программным объектам осуществляется при помощи специального программного интерфейса (API), который включает в себя один интерфейс и десять классов, охватывающих весь спектр программных объектов, встречающихся в PHP.
interface Reflector
class Reflection
class ReflectionException extends Exception
class ReflectionFunction implements Reflector
class ReflectionParameter implements Reflector
class ReflectionMethod extends ReflectionFunction
class ReflectionClass implements Reflector
class ReflectionObject extends ReflectionClass
class ReflectionProperty implements Reflector
class ReflectionExtension implements Reflector
Интерфейс Reflection объявляет единственный статический метод export, который определен во всех остальных классах, кроме класса ReflectionException. Этот метод выводит информацию о программном объекте. Для идентификации объекта используется один или два параметра (в зависимости от конкретного класса). Последний, необязательный, параметр, по умолчанию равный false, используется
для отключения вывода на экран (при этом информация об объекте возвращается в виде строки).
ReflectionFunction::export('phpinfo');
Function [ <internal> public function phpinfo ] {
}
Вы можете самостоятельно ознакомиться с переменными и методами классов, входящих в API, используя метод export класса ReflectionClass.
Шаблон делегирования
Рассмотрим использование рефлексии для реализации еще одного шаблона проектирования.
В ситуации, когда один класс должен расширять функциональность другого класса, обычно используется механизм наследования. Однако, не во всех случаях наследование оправдано, а иногда и вообще невозможно (например, когда характер взаимоотношений между классами не вполне ясен или класс уже наследует какому-то классу). Решение может быть основано на использовании шаблона делегирования (Delegation Pattern).
Прежде всего, необходимо определить сами классы (их может быть и больше двух).
<?php
class Foo {
public function foo()
{
return __METHOD__;
}
}
class Bar {
public function bar()
{
return __METHOD__;
}
}
?>
Затем определим класс, осуществляющий делегирование. Переменная $registeredObjects служит для хранения зарегистрированных объектов, а метод addObject - для добавления (регистрации) новых объектов. Кроме того, для делегирования вызова соответствующему объекту необходимо перекрыть магический метод __call (при этом поиск объекта будет осуществляться в том порядке, в котором объекты были зарегистрированы).
<?php
class Delegator {
private $registeredObjects;
public function addObject($o)
{
$this->registeredObjects[] = $o;
return null;
}
public function __call($method, $args)
{
foreach ($this->registeredObjects as $o) {
$c = new ReflectionClass($o);
if ($m = $c->getMethod($method)) {
if ($m->isPublic() && !$m->isAbstract()) {
return $m->invoke($o, $args);
}
}
}
}
}
?>
Нам остается лишь создать объект класса-делегатора и зарегистрировать вновь созданные объекты основных классов, после чего можно вызывать их методы (при этом они вызываются не напрямую, а через класс-делегатор).