Пытаясь изобрести свой метод toArray()
1 для сериализации объектов в ассоциативный массив наткнулся на пару интересных моментов.
Методы method_exists
и is_callable
Можно предположить, что is_callable
будет возвращать true
для всех методов где method_exists
возращает true
. Но в действительности это не так.
var_dump(is_callable($class, '__toString')); // bool(false)
var_dump(method_exists($class, '__toString')); // bool(true)
Доступ к закрытым и защищенным свойствам
И существование документированной фичи, что при явном приведении типа объекта к массиву, можно получить содержимое скрытых свойств. Так следующий код:
class A {private $private = 0;}
class B extends A {protected $protected = 1; private $private2 = 2; public $public = 3;}
$x = new B();
echo json_encode((array)$x, JSON_PRETTY_PRINT);
выведет:
{
"\u0000*\u0000protected": 1,
"\u0000B\u0000private2": 2,
"public": 3,
"\u0000A\u0000private": 0
}
Где \u0000
обозначает символ машинного нуля в JSON.
До появления PHP 5.4 это было единственным способом получения значений защищенных членов класса без использования Reflection (который все-таки довольно медленный и неуклюжий). Сейчас же можно воспользоваться анонимными функциями и привязыванием конекста: https://ocramius.github.io/blog/accessing-private-php-class-members-without-reflection/
-
апдейт, есть вероятность, что эта функциональность таки попадет в сам язык https://wiki.php.net/rfc/to-array ↩︎