Какова реальная цель магического метода __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.

Сравните два:

  1. var_dump ($ а)

    object (A) # 1 (2) {["var1"] => int (5) ["var2"] => string (3) "foo"}

  2. var_export ($ а)

    A:: __set_state (массив ('var1' => 5, 'var2' => 'foo',))

  3. (бонус) сериализация ($ 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 - нет магии там. Но это только мое скромное мнение.

Другие вопросы по тегам