Intereting Posts
Symfony security возвращает 401 ответ вместо перенаправления Пропустить Checkout в Magento для загружаемого продукта Как использовать маршрутизацию laravel для неизвестного количества параметров в URL? Как показать индикатор выполнения при загрузке, используя ajax Заполнение таблицы HTML из ответа AJAX предотвращать кеш кнопки назад браузера Как использовать разбиение на страницы laravel с помощью построителя запросов Laravel – правило валидации max не работает над загруженным изображением Как я могу передать данные из HTML-формы в файл JavaScript, который обрабатывает вызовы AJAX Как я могу отправить 2 разных PHP-массива в JavaScript? SimpleXML получает элемент Элемент между дочерними элементами Как обновить PRIMARY KEY / FOREIGN KEY в других связанных таблицах? Проблема с соединением Db2 с IBM DB2 css не работает при отправке электронной почты с использованием AWS Что такое функция обратного вызова и как использовать ее с OOP

php reflection получает свойства без получения свойств базового класса

Поэтому я работаю с классом настроек, который расширяет базовый класс настроек, который будет похож на «глобальные настройки». Существует несколько сервисов, и каждая служба имеет свой собственный класс настроек, который расширяет класс базовых настроек. Класс абстрактных базовых настроек соответствует настройкам, которые совместно используются службами. Поэтому сначала я проиллюстрирую приведенный ниже пример, а затем определю проблему:

пример:

abstract class BaseSettings { protected $settingA; protected $settingB; } class MyServiceSettings extends BaseSettings { private $settingC; public $settingD; } 

проблема:

Если я создам экземпляр ReflectionClass, например …

 $reflect = new ReflectionClass($this); 

.. из класса MyServiceSettings или класса BaseSettings (потому что, очевидно, вы не можете иметь экземпляр абстрактного класса), $reflect->getProperties() всегда будет возвращать свойства как MyServiceSettings, так и BaseSettings (и, я думаю, это потому что мы действительно работаем с одним конкретным классом)

Теперь я уверен, что могу создать пустой класс, который расширяет абстрактный BaseClass, чтобы выяснить, какие свойства идут туда (или просто избавиться от абстрактного и создать экземпляр BaseClass), но это кажется довольно грязным, поэтому мне интересно, есть, пожалуй, более элегантный способ определить, какие свойства принадлежат родительскому классу и которые принадлежат к дочернему классу?

Если вам интересно, почему я это делаю, я инициализирую настройки в файл .json для функции восстановления, которую я добавил, чтобы продолжить работу с последней успешной завершенной атомной операцией. Почему я должен делать это таким образом – ограничение окружающей среды.

Я бы сделал так:

 $class = new ReflectionClass('Some_class_name'); $properties = array_filter($class->getProperties(), function($prop) use($class){ return $prop->getDeclaringClass()->getName() == $class->getName(); }); 

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

Хотя выше будет работать только для настроек MyServiceSettings , когда вы вызываете этот метод из класса BaseSettings , он все равно будет возвращать свойства для класса, который его расширяет (если вы имеете дело с экземпляром класса BaseSettings где класс BaseSettings был расширен другим классом – независимо от того, BaseSettings класс BaseSettings является абстрактным или конкретным), по крайней мере, когда вы ссылаетесь на базовый класс как $this изнутри базового класса.

Возможно, есть более эффективная работа, но тот, который я нашел, – это просто использовать

 $reflectionClass = new ReflectionClass(get_parent_class($this)); 

просто для иллюстрации примера того, как вы могли бы это использовать, вот адаптация функции, которую я использую для десериализации класса и его базового класса:

 // "attribute" to be used in doc comments if it should not be // serialized / deserialized // ( remember: /** ... */ doc comments must have two asterisks!! ) private $DoNotSerialize = "[@DoNotSerialize]"; protected function dehydrate(ReflectionClass $reflectionClass) { // if you're using private or protected properties and need to use // $property->setAccessible() if(floatval(phpversion()) < 5.3) { throw new Exception("requires PHP version 5.3 or greater"); } clearstatcache(); $properties = array_filter( $reflectionClass->getProperties(ReflectionProperty::IS_PROTECTED|ReflectionProperty::IS_PUBLIC) , function($prop) use($reflectionClass) { return $prop->getDeclaringClass()->getName() == $reflectionClass->getName(); } ); $settings = null; foreach($properties as $property) { $comment = $property->getDocComment(); if( strpos($comment,$this->DoNotSerialize) !== false ){ continue; } if($property->isProtected()){ $property->setAccessible(TRUE); } if(isset($settings)) { // implementation of array_push_associative // can be found at http://php.net/manual/en/function.array-push.php array_push_associative( $settings , array($property->getName() => $property->getValue($this)) ); } else { $settings = array($property->getName() => $property->getValue($this)); } } //implementation irrelevant here writeToFile($reflectionClass->getName(), $settings); if(get_parent_class($reflectionClass)) { $this->dehydrate(get_parent_class($reflectionClass)); } }