Массив к объекту и объекту в массив в PHP - интересное поведение
Можете ли вы объяснить следующее интересное поведение?
class test {
//Class *test* has two properties, public and private.
public $xpublic = 'x1';
private $xprivate = 'x2';
}
$testObj = new test();
Преобразуем $testObj
в массив.
settype($testObj, 'array');
var_dump($testObj);
Результат:
array(2) {
["xpublic"]=> string(3) "x1"
["testxprivate"]=> string(4) "x2"
}
ОК, xprivate
свойство становится testxprivate
Позвольте преобразовать этот массив в объект.
$newObj = (object)$testObj;
var_dump($newObj);
Результат:
object(stdClass)#1 (2) {
["xpublic"]=> string(3) "xxx"
["xprivate":"test":private]=> string(4) "xxx3"
}
$newObj
- объект stdClass
.
И вопрос:
Почему testxprivate
становится частным свойством xprivate
(not testxprivate
) нового объекта? Как PHP знает, что массив $testObj
был объектом?
Если я определяю равный массив:
$testArray = array('xpublic'=>'x1', 'testxprivate'=>'x2');
а затем преобразуйте его в объект:
var_dump((object)$testArray);
Я получу объект с двумя общедоступными свойствами xpublic
и testxprivate
, как ожидалось:
object(stdClass)#2 (2) {
["xpublic"]=> string(2) "x1"
["testxprivate"]=> string(2) "x2"
}
Ответы
Ответ 1
Ключ массива содержит маркер, который должен быть частным свойством теста класса.
Сравните выходные данные скриптов со следующим:
$array = array(
"xpublic" => "x1",
# this will become a private member:
"\x00test\x00xprivate" => "x2",
# this will become a protected member:
"\x00*\x00xprotected" => "x3"
);
var_dump($array);
$obj = (object) $array;
var_dump($obj);
При сериализации одна и та же строка используется для описания частных членов.
Вывод:
array(3) {
["xpublic"]=>
string(2) "x1"
["testxprivate"]=>
string(2) "x2"
["*xprotected"]=>
string(2) "x3"
}
object(stdClass)#1 (3) {
["xpublic"]=>
string(2) "x1"
["xprivate":"test":private]=>
string(2) "x2"
["xprotected":protected]=>
string(2) "x3"
}
В выводе var_dump()
нулевые байты не видны.
(Обновление: добавлен защищенный член класса)
Ответ 2
Вероятно, PHP-движок сохраняет структуру класса внутри себя и просто дает какую-то оболочку массива, и, таким образом, при повторном ее повторении он остается закрытым, хотя я не могу гарантировать это на 100%.