Как программно найти открытые свойства класса внутри одного из его методов

У меня есть класс Foo с общедоступными и защищенными свойствами. Foo должен иметь нестатический метод getPublicVars(), который возвращает список всех общедоступных свойств Foo (это просто пример, который я знаю извне объекта Foo, вызывающего get_object_vars() выполнит это, и мне не нужен мой метод getPublicVars()).

Примечание.. Это также должно возвращать динамически объявленные свойства, назначенные во время выполнения, экземпляру класса (объекту), которые не определены в определении класса.

Вот пример:

class Foo{
    private $bar = '123';
    protect $boo = '456';
    public   $beer = 'yum';

   //will return an array or comma seperated list
   public function getPublicVars(){
      // thar' be magic here...
   } 
}

 $foo = new Foo();
 $foo->tricky = 'dynamically added var';

 $result = $foo->getPublicVars();  
 var_dump($result); // array or comma list with 'tricky' and 'beer'   

Каков наиболее сжатый способ получить только общедоступные свойства объекта изнутри собственного метода класса, в котором видны как общедоступные, так и защищенные?

Я посмотрел:

Но это не похоже на мой вопрос, поскольку он указывает на использование get_object_vars() вне объекта.

Ответ 1

Как вы уже поняли, PHP-сборка get_object_vars зависит от области. Вы хотите только свойства объекта public.

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

function get_object_public_vars($object) {
    return get_object_vars($object);
}

Вызов этого get_object_public_vars даст вам только общедоступные свойства, потому что он выходит за пределы текущего объекта.

Если вам нужен более мелкозернистый элемент управления, вы также можете использовать ReflectionObject:

(new ReflectionObject($this))->getProperties(ReflectionProperty::IS_PUBLIC);

Что имеет то преимущество, что вам не нужно вводить другую функцию в глобальном пространстве имен.

Ответ 2

Не работает с версией php >= 7
Таким образом, я больше не могу рекомендовать решение.
Вместо этого используйте отражение

Чтобы получить общедоступные свойства внутри класса

$publicProperties = call_user_func('get_object_vars', $this);

"трюк" заключается в том, что get_object_vars вызывается из области call_user_func, а не сфера действия объекта

нет необходимости в отражении, автономных функциях, замыканиях и т.д.

Ответ 3

В соответствии с этой статьей (написанной Вэнсом Лукасом) вы можете создать новую область вызова внутри определения класса Foo, используя "анонимной" функции, а затем вы можете вызвать get_object_vars() изнутри. Это позволит вам получить только общедоступные свойства внутри вашего класса, даже если они были созданы динамически позже извне.

Таким образом, для вашего примера это будет:

<?php
class Foo {
    private $bar = '123';
    protected $boo = '456';
    public   $beer = 'yum';

   // return an array of public properties 
   public function getPublicVars(){
      $publicVars = create_function('$obj', 'return get_object_vars($obj);');
        return $publicVars($this);
   } 
}

 $foo = new Foo();
 $foo->tricky = 'dynamically added var';

 $result = $foo->getPublicVars();  
 print_r($result);

и вывод будет:

Array
(
    [beer] => yum
    [tricky] => dynamically added var
)

В упомянутой выше статье есть второй пример, который показывает другой способ сделать то же самое с использованием так называемых "замыканий" (от php 5.3), но по какой-то причине он не работает для меня с php v5.4 поэтому частные и защищенные свойства остаются включенными в результирующий массив.