Відображення PHP (class ReflectionClass)

337

Від автора: при розробці веб-додатків іноді необхідно отримувати інформацію про структуру того чи іншого класу. Причому, цю інформацію, необхідно отримувати програмно. Для вирішення даної задачі, застосовуються відображення. Відображення – це спеціальний клас мови PHP, який містить безліч різних методів отримання інформації про структуру довільного класу.

Відображення PHP (class ReflectionClass)Відображення PHP (class ReflectionClass)

1. Постановка задачі

Для сьогоднішнього уроку, я підготував такий файл:

interface ITest3 {
}
}
abstract class ATest {
public $parent = TRUE;
}
/**
*
*
*@param foo bar
*@return baz
*/
class Test extends ATest implements ITest{
private $priv = 1;
protected $pro;
public $pub = ‘str’;
const MY_CONST = “constructor “;
const MY_CONST2 = “destructor”;
static $_ins = “instance”;
static $_ins1 = “instance1”;
public function __construct() {
echo self::MY_CONST;
}
public function __destruct() {
echo self::MY_CONST2;
}
public function my_method($v) {
echo $v.self::$_ins;
}
}

В даному файлі створено дуже простий клас (для прикладу), який успадковує абстрактний клас ATest і реалізує інтерфейс ITest. Тепер, використовуючи відображення, ми отримаємо практично всю інформацію про структуру даного класу. Як я говорив спочатку – це відображення спеціальний клас PHP, а більш точно це набір класів. Кожен з яких, містить методи, що дозволяють отримати детальну інформацію по класу, методу, властивості і т. д.

Перед тим як почати хотів би звернути Вашу увагу на наступну сторінку: ua1.php.net/manual/ru/book.reflection.php. Тут представлена довідкова інформація. Як Ви бачите, до відбиттям належать декілька класів. Але ми з Вами в цьому уроці, розглянемо методи класу ReflectionClass, які дозволяють отримати інформацію по довільному класу. І трохи торкнемося клас ReflectionMethod, який дозволяє отримати інформацію про методи класів.

2. Клас ReflactionClass

Насамперед, необхідно створити об’єкт класу ReflectionClass і передати його конструктору ім’я класу, інформацію якого потрібно отримати в майбутньому. Так як у нас створений тестовий клас Test, його назву і передаємо:

$obj = new ReflectionClass(‘Test’);

Тепер, давайте отримаємо масив всіх констант оголошених в класі, для цього використовуємо метод getConstants():

print_r($obj->getConstants());

Зверніть увагу, що метод getConstants(), я викликаю і відразу ж передаю його у метод print_r(). Що б у браузері побачити результат. Цей прийом я буду використовувати на протязі всього уроку.

Відображення PHP (class ReflectionClass)

Як Ви бачите, ми дійсно отримуємо масив з оголошених констант. Для отримання значення довільної оголошеної константи класу, скористаємося наступним методом getConstant():

print_r($obj->getConstant(MY_CONST2));

Даним методом параметром необхідно передати ім’я константи, значення якої хочемо отримати. Далі, метод getDefaultProperties(), дозволяє отримати масив, оголошених властивостей у класі:

print_r($obj->getDefaultProperties());

На екрані ми побачимо наступне:

Відображення PHP (class ReflectionClass)

Якщо в класі є блок коментарів, які приміром пояснюють його роботу, то його зміст можна отримати, використовуючи метод getDocComment():

print_r($obj->getDocComment());

Зверніть увагу, що даний метод поверне зміст коментарів, які безпосередньо відносяться до розглянутого класу. Тобто коментарі, які описані, безпосередньо перед класом. Ім’я файлу, в якому описаний розглянутий клас можна отримати за допомогою методу getFileName():

print_r($obj->getFileName());

Далі, дізнатися які інтерфейси реалізує даний клас, можна використовуючи метод getInterfaces():

print_r($obj->getInterfaces());

На екрані ми побачимо наступне:

Відображення PHP (class ReflectionClass)

Як Ви бачите, ми отримуємо масив, у кожної клітинки даного масиву ми отримуємо об’єкт, який характеризує один з реалізують інтерфейсів. І цей об’єкт – це об’єкт класу ReflectionClass, для даного інтерфейсу. Тобто даний об’єкт, ми можемо використовувати для одержання інформації по конкретному інтерфейсу.

Таким чином ми вже отримали інформацію не тільки про структуру даного класу, але і про інтерфейсах, які він реалізує. Наприклад, ми можемо зробити наступне. Ми можемо дізнатися, в якому файлі описаний інтерфейс, що реалізується даними даним класом:

$i = $obj->getInterfaces();
print_r($i[‘ITest’]->getFileName());

Описані методи в класі, можна отримати, використовуючи метод getMethods():

print_r($obj->getMethods());

При цьому ми отримаємо наступний масив:

Відображення PHP (class ReflectionClass)

Як Ви бачите, цей масив містить в собі стільки клітинок, скільки методів описаної в класі, при чому імена ключів, це імена методів. А значення клітинок – це об’єкти класу ReflectionMethod, який дозволяє отримати всю інформацію про метод. У даному уроці ми його практично не розглядаємо. Але він схожий у своєму застосуванні на ReflectionClass тому Ви цілком самостійно розберетеся.

У класі ReflectionMethod ми розглянемо дуже корисний метод invoke(), який дозволяє викликати на виконання метод класу. До прикладу, давайте викличемо на виконання метод my_method(), не вручну, а програмно:

$m = $obj->getMethods();
$m[2]->invoke(new Test(),’hello world ‘);

Зверніть увагу: ми програмно отримуємо масив методів, описаних в класі і викликаємо метод, який міститься у клітинці з індексом 2. При цьому метод invoke(), першим параметром отримує об’єкт класу, до якого необхідно викликати метод (ми його на льоту створюємо new Test()) і наступними параметрами, передаємо аргументи, які необхідні для адресата методу. На екрані ми побачимо наступне:

Відображення PHP (class ReflectionClass)

Тобто, ми бачимо відпрацювання конструктора, потім методу my_method() і деструктора. Ім’я класу, з яким ми працюємо, можна отримати, використовуючи метод getName():

print_r($obj->getName());

Використовуючи метод getParentClass(), ми отримаємо об’єкт ReflectionClass для класу, який є батьком розглянутого.

print_r($obj->getParentClass());

Для роботи з властивостями класу використовується об’єкт класу ReflectionProperty, об’єкт якого можна отримати звичайним чином (new ReflectionProperty() і передавши його конструктору ім’я властивості). Для даного розглянутого класу, можна отримати масив. У кожній клітинці якого будуть містяться об’єкти класу ReflectionProperty, для кожного описаного властивості. Для цього необхідно використовувати метод getProperties():

print_r($obj->getProperties());

На екрані ми побачимо наступне:

Відображення PHP (class ReflectionClass)

Якщо Вас цікавить певної властивість класу. То об’єкт класу ReflectionProperty, для нього можна отримати, використовуючи метод getProperty(), відповідно, передавши йому ім’я властивості:

print_r($obj->getProperty(‘priv’));

Масив статичних властивостей класу, можна отримати, використовуючи метод getStaticProperties(). При цьому це буде звичайний масив, де ключі – це імена статичних властивостей, а значення клітинок – це значення статичних властивостей.

print_r($obj->getStaticProperties());

Значення певного статичного властивості, можна отримати, використовуючи метод getStaticPropertyValue(), передавши йому ім’я властивості:

print_r($obj->getStaticPropertyValue(‘_ins1’));

Перевірити, чи можливо створити об’єкт даного класу, можна використовуючи метод isInstantiable(). Який поверне TRUE, якщо можна створити об’єкт розглянутого класу. Відповідно якщо необхідно створити об’єкт класу програмно, для цього використовується метод newInstance(). Наприклад, можна написати наступне:

if($obj->isInstantiable()) {
$c = $obj->newInstance();
if($obj->isInstance($c)) {
echo “yes”;
}
}
else {
echo “No”;
}

Тобто перевіряємо, чи можна створити об’єкт розглянутого класу (у нашому випадку це клас Test), далі створюємо його об’єкт і перевіряємо, чи справді у змінній $c, міститься об’єкт розглянутого класу. Використовуючи метод isInstance(), який приймає параметром об’єкт для перевірки (даний метод поверне TRUE, якщо дійсно переданий об’єкт, є об’єктом розглянутого класу). При цьому на екрані ми побачимо наступне:

Відображення PHP (class ReflectionClass)

Ось і все, що я хотів показати Вам у цьому уроці. Дивіться відображення дуже корисно, якщо Ви у своєму скрипті створюєте механізм автоматичного завантаження різних файлів з класами. Приміром, у Вас є безліч різних файлів. З них Вам необхідно відбирати тільки ті, які реалізують певний інтерфейс і є нащадками певного батьківського класу. А це дуже легко визначити за допомогою вивчених методів. Більш того Ви можете перевірити, чи є у класу потрібний метод, і якщо так, то викликати його на виконання.

На цьому даний урок завершено. Все Вам доброго і вдалого кодування!!!