Отражения PHP (class ReflectionClass)

Отражения PHP (class ReflectionClass)

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

скачать исходникискачать урок

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

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

interface ITest3 {
	
}

interface ITest {
	
}

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(). Что бы в браузере увидеть результат. Данный прием я буду использовать на протяжении всего урока.

Как Вы видите, мы действительно получаем массив из объявленных констант. Для получения значения произвольной объявленной константы класса, воспользуемся следующим методом getConstant():

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

Данному методу параметром необходимо передать имя константы, значение которой хотим получить. Далее, метод getDefaultProperties(), позволяет получить массив, из объявленных свойств в классе:

print_r($obj->getDefaultProperties());

На экране мы увидим следующее:

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

print_r($obj->getDocComment());

Обратите внимание, что данный метод вернет содержание комментариев, которые непосредственно относятся к рассматриваемому классу. То есть комментарии, которые описаны, непосредственно перед классом. Имя файла, в котором описан рассматриваемый класс можно получить при помощи метода getFileName():

print_r($obj->getFileName());

Далее, узнать какие интерфейсы реализует данный класс, можно используя метод getInterfaces():

print_r($obj->getInterfaces());

На экране мы увидим следующее:

Как Вы видите, мы получаем массив, в каждой ячейки данного массива мы получаем объект, который характеризует один из реализующих интерфейсов. И этот объект – это объект класса ReflectionClass, для данного интерфейса. То есть данный объект, мы можем использовать, для получения информации по конкретному интерфейсу.

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

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

Описанные методы в классе, можно получить, используя метод getMethods():

print_r($obj->getMethods());

При этом мы получим следующий массив:

Как Вы видите, этот массив содержит в себе столько же ячеек, сколько методов описанной в классе, при чем имена ключей, это имена методов. А значения ячеек – это объекты класса ReflectionMethod, который позволяет получить всю информацию о методе. В данном уроке мы его практически не рассматриваем. Но он похож в своем применении на ReflectionClass поэтому Вы вполне самостоятельно разберетесь.

В классе ReflectionMethod мы рассмотрим очень полезный метод invoke(), который позволяет вызвать на исполнение метод класса. К примеру, давайте вызовем на исполнение метод my_method(), не вручную, а программно:

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

Обратите внимание: мы программно получаем массив методов, описанных в классе и вызываем метод, который содержится в ячейке с индексом 2. При этом метод invoke(), первым параметром получает объект класса, у которого необходимо вызвать метод (мы его на лету создаем new Test()) и последующими параметрами, передаем аргументы, которые необходимы для вызываемого метода. На экране мы увидим следующее:

То есть, мы видим отработку конструктора, затем метода my_method() и деструктора. Имя класса, с которым мы работаем, можно получить, используя метод getName():

print_r($obj->getName());

Используя метод getParentClass(), мы получим объект ReflectionClass для класса, который является родителем рассматриваемого.

print_r($obj->getParentClass());

Для работы со свойствами класса используется объект класса ReflectionProperty, объект которого можно получить обычным образом (new ReflectionProperty() и передав его конструктору имя свойства). Либо для данного рассматриваемого класса, можно получить массив. В каждой ячейке, которого будут содержатся объекты класса ReflectionProperty, для каждого описанного свойства. Для этого необходимо использовать метод getProperties():

print_r($obj->getProperties());

На экране мы увидим следующее:

Если Вас интересует определенной свойство класса. То объект класса 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, если действительно переданный объект, является объектом рассматриваемого класса). При этом на экране мы увидим следующее:

Вот и все, что я хотел показать Вам в этом уроке. Смотрите отражения очень полезно использовать, если Вы в своем скрипте создаете механизм автоматической загрузки различный файлов с классами. К примеру, у Вас есть множество различных файлов. Из них Вам необходимо отбирать только те, которые реализуют определенный интерфейс и являются потомками определенного родительского класса. А это очень легко определить при помощи изученных методов. Более того Вы можете проверить, есть ли у класса нужный метод и если да, то вызвать его на исполнение.

На этом данный урок завершен. Все Вам доброго и удачного кодирования!!!

Фреймворк YII2: теория и первая практика

Овладейте азами фреймворка Yii2 за 5 дней!

Получить

Метки: ,

Комментарии Вконтакте:

Комментарии Facebook:

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *

Можно использовать следующие HTML-теги и атрибуты: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

Я не робот.

Spam Protection by WP-SpamFree