Какова реальная цель магического метода __set_state в PHP?
Я изучаю магические методы, читаю каждый сайт, беру каждый пример, но для меня ничего не имеет смысла. Примеры как это:
class A
{
public $var1;
public $var2;
public static function __set_state($an_array) // As of PHP 5.1.0
{
$obj = new A;
$obj->var1 = $an_array['var1'];
$obj->var2 = $an_array['var2'];
return $obj;
}
}
$a = new A;
$a->var1 = 5;
$a->var2 = 'foo';
eval('$b = ' . var_export($a, true) . ';'); // $b = A::__set_state(array(
// 'var1' => 5,
// 'var2' => 'foo',
// ));
var_dump($b);
Какова реальная цель? Это для отладки или что-то?
2 ответа
__set_state
вызывается в ответ на передачу вашего объекта в var_export
функция.
var_export
Выводит или возвращает анализируемое строковое представление переменной.
var_export
принимает необязательный второй параметр - логическое значение, которое определяет, будет ли возвращаемая после строки переменная в качестве первого аргумента строка вместо вывода.
Пример:
class Dummy {
private $value1_;
private $value2_;
function __construct() {
$this->value1_ = 100;
$this->value2_ = "100";
}
static function __set_state(array $array) {
foreach($array as $k => $v) {
echo("$k ==> $v <br/>");
}
}
}
$aDummy = new Dummy();
//var_export by it self will output Dummy::__set_state(array( 'value1_' => 100, 'value2_' => '100', ))
var_export($aDummy);
eval(var_export($aDummy, true) . ';');
Теперь вывод таков:
value1_ ==> 100
value2_ ==> 100
var_export
может создать исполняемый код PHP для типа Dummy с __set_state
метод определен.
var_export
принимает один аргумент, и это должен быть массив. Он будет содержать пары ключ-значение свойств или полей экземпляра, для которого он вызывается.
Вы можете положить все, что вы хотите в __set_state
метод.
__set_state
может быть понято в связи с var_export
Если вы читаете документы:
var_export () получает структурированную информацию о данной переменной. Это похоже на var_dump() с одним исключением: возвращаемое представление является допустимым кодом PHP.
Сравните два:
var_dump ($ а)
object (A) # 1 (2) {["var1"] => int (5) ["var2"] => string (3) "foo"}
var_export ($ а)
A:: __set_state (массив ('var1' => 5, 'var2' => 'foo',))
(бонус) сериализация ($ a)
O: 1: "А":2:{s:4:"var1"; я:5;s:4:"var2";s:3:"Foo";}
Итак, второй - это действительный код PHP, вы можете запустить его и получить похожий объект.
Так что же произойдет, если вы удалите метод __set_state? Давай попробуем:
class A
{
public $var1;
public $var2;
}
$a = new A;
$a->var1 = 5;
$a->var2 = 'foo';
var_export($a);
// A::__set_state(array( 'var1' => 5, 'var2' => 'foo', ))
Все еще работает, верно? Давайте назовем это тогда
class A
{
public $var1;
public $var2;
}
$a = A::__set_state(array( 'var1' => 5, 'var2' => 'foo', ))
// Exception: Call to undefined method A::__set_state()
Давайте вернем это и посмотрим:
class A
{
public $var1;
public $var2;
public static function __set_state($an_array) // As of PHP 5.1.0
{
$obj = new A;
$obj->var1 = $an_array['var1'];
$obj->var2 = $an_array['var2'];
return $obj;
}
}
$a = A::__set_state(array( 'var1' => 5, 'var2' => 'foo', ));
var_dump($a);
// object(A)#1 (2) { ["var1"]=> int(5) ["var2"]=> string(3) "foo" }
Так что реальная цель __set_state
метод заключается в инициализации объекта в случае, если кто-то "сериализует" его var_export
,
Зачем кому-то это нужно? Объекты, сериализованные с serialize
должны быть несериализованы с unserialize
, Но объекты, сохраненные в файлах var_export
может быть просто включен, потому что это просто правильный код PHP.
Редактировать:
Я бы не стал называть этот метод magic
(даже если это описано в документации), так как в этом нет ничего волшебного. PHP просто предполагает, что это там, когда var_export
называется, и он должен быть там, если вы хотите использовать все, что var_export
производится. Я бы сказал, что это просто соглашение, которое называется __set_state
- нет магии там. Но это только мое скромное мнение.