Отправляет email-рассылки с помощью сервиса Sendsay

PHP 5: Новые возможности.

  Все выпуски  

Рефлексия


Вниманию читателей!

Отдельные выпуски рассылки в той или иной мере взаимосвязаны; особенно, это относится к материалам практических занятий.

С предыдущими выпусками Вы можете ознакомиться:

  1. в архиве рассылки (оригиналы выпусков);
  2. на сайте рассылки (исправленные и дополненные версии).

# # #

Вы также можете подписаться на рассылку "PHP 5 для начинающих".

PHP 6 уже в разработке!

Еще в ноябре 2005 года на встрече в Париже разработчики обсудили новые возможности следующей, шестой, версии PHP. Интересует ли Вас, какой будет эта версия? Примите участие в опросе, который проводится на сайте рассылки.

http://pterodactyl.l2p.net/e107/

[опрос на английском языке: PHP 6: Are you interesting in? (PHP 6: Вы зантересованы?) - YES (ДА) - NO (НЕТ)]

PHP 5: Новые возможности.

The Pterodactyl

Copyright 2006 Pterodactyl's School

28.04.2006

История переиздания
Издание 1.00 [ Дата ]
Первоначальная версия.

Аннотация

Доступ к программным объектам скрипта во время его исполнения при помощи рефлексии; API. Шаблон делегирования.


PHP и раньше обеспечивал возможность доступа к некоторым программным объектам во время исполнения скрипта при помощи переменных (например, вызов функций или создание классов с помощью оператора new). Однако, PHP 5 предоставляет действительно полноценный и гибкий механизм такого доступа, который называется рефлексией (reflection), или интроспекцией (introspection).

Замечание

Строго говоря, такой механизм предоставляет не сам PHP 5, а движок, на котором он работает, - Zend Engine [1].

Доступ к программным объектам осуществляется при помощи специального программного интерфейса (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 ] {
}
        
print ReflectionFunction::export('phpinfo', true);
Function [ <internal> public function phpinfo ] {
}
        
function foo($bar) {
    return null;
}

ReflectionFunction::export('foo');
        
Function [ <user> <visibility error> function foo ] {
  @@ Command line code 1 - 1

  - Parameters [1] {
    Parameter #0 [ <required> $bar ]
  }
}
        
ReflectionClass::export('stdClass');
Class [ <internal> class stdClass ] {

  - Constants [0] {
  }

  - Static properties [0] {
  }

  - Static methods [0] {
  }

  - Properties [0] {
  }

  - Methods [0] {
  }
}
        

Подсказка

Вы можете самостоятельно ознакомиться с переменными и методами классов, входящих в 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);
                }
            }
        }
    }
}

?>
        

Нам остается лишь создать объект класса-делегатора и зарегистрировать вновь созданные объекты основных классов, после чего можно вызывать их методы (при этом они вызываются не напрямую, а через класс-делегатор).


<?php

$delegator = new Delegator;

$delegator->addObject(new Foo);
$delegator->addObject(new Bar);

print $delegator->foo();

?>
        
Foo::foo

Created with DocBook Created with Libxslt


В избранное