php Отражения (Reflection). Что это? Механизм создания.

Отражения в php - это набор классов (Reflection***), позволяющий разработчику исследовать пользовательские и предопределённые классы.
Отражения хранят информацию о классах / методах / свойствах.

В частности статья является ответом на эти вопросы:

  1. При создании отражения некоторого класса (ReflectionClass), отражения его параметров(ReflectionParameter) и методов (ReflectionMethod) формируются сразу же, автоматически или только при их явном вызове ( например ReflectionClass::getPMethods())?

    Давайте рассмотрим механизм создания отражения класса. Что происходит в самом начале? Создаётся объект класса ReflectionClass:

    $className = 'MyClass';
    
    $obj = new ReflectionClass($className);

    Как видно из документации класса ReflectionClass, объект $obj содержит только одно свойство - name, в котором хранится название класса, информацию о котором хранит отражение:

    echo $obj->name; // MyClass

    Думаю, можно сделать вывод, что объекты ReflectionMethod и ReflectionProperty (обратите внимание, что класс ReflectionParameter, упомянутый в вопросе, относится к параметрам функции, а не свойствам класса), хранящие данные о методах и свойствах класса создаются при вызове методов ReflectionClass::getProperties() и ReflectionClass::getMethods() соответственно, а не при инстанцировании ReflectionClass.

  2. С чем связана, такая несколько на мой взгляд странная система наследования свойств и методов в отражениях, при которой метод getMethods() возвращает список всех методов класса, в том числе и закрытых, унаследованных от базового, а метод getProperties() закрытых свойств родительского объекта не наследует?

    Действительно, логично, что приватные свойства не наследуются, поэтому не возвращаются методом getProperties(). А вот почему наследуются приватные методы - не понятно. (данный факт указан в "PHP в подлиннике" Д. Котеров, стр. 577, и проверен на практике :)))

    Кстати, вызвать унаследованные приватные методы с помощью метода invoke() не получится :

    Uncaught ReflectionException: Trying to invoke private method ...

    Ниже код для исследования:

    <?php
    
    error_reporting(E_ALL);
    ini_set('display_errors', true);
    
    class Base
    {
        public $basePublicProp;
        
        protected $baseProtectedProp;
        
        private $basePrivateProp;
        
        public function basePublicMethod()
        {
            echo "Привет, я ".__METHOD__."<br>";
        }
        
        protected function baseProtectedMethod()
        {
            echo "Привет, я ".__METHOD__."<br>";
        }
        
        private function basePrivateMethod()
        {
            echo "Привет, я ".__METHOD__."<br>";
        }
    }
    
    class myClass extends Base
    {
        public $publicProp;
        
        protected $protectedProp;
        
        private $privateProp;
        
        public function publicMethod()
        {
            echo "Привет, я ".__METHOD__."<br>";
        }
        
        protected function protectedMethod()
        {
            echo "Привет, я ".__METHOD__."<br>";
        }
        
        private function privateMethod()
        {
            echo "Привет, я ".__METHOD__."<br>";
        }
    }
    
    $className = 'MyClass';
    
    echo "<p>Создаём объект отражения для класса MyClass... <br><br>";
    $obj = new ReflectionClass($className);
    
    // 1)
    echo "Как видим, объект ReflectionClass имеет только одно "
     ."свойство, name: <br>";
    echo "<pre>";
    print_r($obj);
    echo "</pre>";
    
    echo "<br> вот его значение: ";
    echo $obj->name;
    
    // 2)
    echo "</p><hr><p> Посмотрим, какие методы 'видит' "
     ."отражение... <br>";
    $methods = $obj->getMethods();
    
    echo "<br> Как видим, отражение предоставляет доступ даже "
     ."к приватным методам базового класса: <br>";
    echo "<pre>";
    print_r($methods);
    echo "</pre>";
    
    echo "<br> Но если попытаться вызвать приватный унаследованный "
     ."метод, выбрасвается ReflectionException: <br>";
    //$obj->getMethod('basePrivateMethod')->invoke(new MyClass());
    
    // 3)
    echo "</p><hr><p> Посмотрим, какие свойства 'видит' "
     ."отражение... <br>";
    $props = $obj->getProperties();
    
    echo "<br> Как видим, отражение предоставляет доступ "
     ."ко всем свойствам класса MyClass и к публичным и "
     ."защищённым свойствам базового класса: <br>";
    echo "<pre>";
    print_r($props);
    echo "</pre>";
    
    die('12313');