Во время разработки может потребоваться изменить формат данных по каким либо причинам. Работать с объектами не всегда может быть удобно.

В php объект можно преобразовать в массив, таким образом, что свойства объекта станут индексами ассоциативного массива. Я нашел 2 способа для этого (дабы не раздувать пост фрагментами кода, результаты print_r() будут везде опущены, кому интересно, можете попробовать сами):

  1. Можно просто сменить тип переменной, которая содержит объект:

    $a = new A(); // Создали некий объект A
    $a = (array) $a; // Превратили объект в массив

    В данном подходе есть одно но. У меня лично возникли проблемы с protected и privat свойствами объекта, индексы не видятся, хотя в сети нашел примеры, в которых показано, что защищенные свойства объекта попадают в массив, просто имя индекса берется не просто из имени свойства, а подставляется префикс, в зависимости от свойства protected или privat. У меняв отладчике индексы не отображаются совсем. При попытке вывести через print_r($a), индексы в виде иероглифов отображаются.

  2. Второй способ преобразовать объект в массив - функция get_object_vars().

    Но почему-то и с ней возникла неопределенность. В простом примере, который я набрасывал для проверки работы функции с защищенными свойствами (protected), функции возвращает массив только public свойств объекта:

    class B {
    protected $name = "Alex";
    }

    class A extends B {
    public $name2 = "Alex2";
    }

    $a = new A();
    $a = get_object_vars($a);
    print_r($a);

    Но при попытке использовать в реальном коде проекта, где примерно такая же структура кода, как и в простом примере выше, функция возвращала мне и protected, и private свойства, которые содержатся в родительском классе. Вообщем встал на грабли...

    После некоторых экспериментов выяснил то, что функция возвращает защищенные или только публичные (public) свойства объекта в зависимости от контекста вызова функции (кстати тоже самое касается 3 способа, получения свойств объекта в массив через цикл). Я не знаю баг это или так было задумано, но работает это так:

    function publci_get_vars($obj){
    return get_object_vars($obj);
    }

    class B {
    protected $nameProtected = "AlexProtected";
    private $namePrivate = "AlexPrivate";
    public $last = "NikolaevPublic";
    }

    class A extends B {
    public $namePublic = "AlexPublic";
    private $lastPrivate = "NikolaevPrivate";
    protected $lastprotected = "Nikolaevprotected";

    function get_vars(){
    $all = get_object_vars($this); // врент все
    $public = publci_get_vars($this); // вернет только public
    return array($all, $public);
    }
    }

    $obj = new A();
    $array = get_object_vars($obj); // вернет только public
    $result = $obj->get_vars();

    print_r($array);
    print_r($result);

    Еще бы попробовать как поведет себя функция при передачи объекта в функцию call_user_func() или call_user_func_array() в виде параметра. И что если вызывается через __call() метод, который находится в другом классе?

  3. Третий способ получения свойств объекта в ассоциативный массив (или автоинкрементный) состоит в реализации простого цикла foreach:

    $obj = new A();

    $vars = array();
    foreach ($obj as $name => $value){
    $vars[$name] = $value;
    }

    print_r($vars);

    Причем если, как и во 2 способе, вызывать цикл непосредственно в теле метода объекта, который мы преобразум, то цикл пройдет и по защищенным свойствам объекта (protected и private), а не только по публичным свойства объекта (public).

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

Прочтите также: