问题
I'm learning about magic methods, reading every site, taking every example, but nothing makes sense to me. Examples like this:
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);
What is the real purpose? Is for debugging or something?
回答1:
__set_state
is called in response to an instance of your object being passed to the var_export
function.
var_export
Outputs or returns a parsable string representation of a variable.
var_export
takes an optional second parameter – a boolean that determines whether after the variable passed as the first argument is returned as a string instead of output.
An example:
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) . ';');
Now the output is this:
value1_ ==> 100
value2_ ==> 100
var_export
can produce executable PHP code for the Dummy type with a __set_state
method defined.
var_export
takes one argument, and it must be an array. It will contain key-value pairs of the properties or fields of the instance on which it is called.
You can put anything you want in the __set_state
method.
回答2:
__set_state
can be understood in relation with var_export
If you read the docs:
var_export() gets structured information about the given variable. It is similar to var_dump() with one exception: the returned representation is valid PHP code.
Compare the two:
var_dump($a)
object(A)#1 (2) { ["var1"]=> int(5) ["var2"]=> string(3) "foo" }
var_export($a)
A::__set_state(array( 'var1' => 5, 'var2' => 'foo', ))
(bonus) serialize($a)
O:1:"A":2:{s:4:"var1";i:5;s:4:"var2";s:3:"foo";}
So the second is a valid PHP code, you can run it and end up with similar object.
So what would happen if you removed __set_state method? Let's try:
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', ))
Still works, right? Let's call it then
class A
{
public $var1;
public $var2;
}
$a = A::__set_state(array( 'var1' => 5, 'var2' => 'foo', ))
// Exception: Call to undefined method A::__set_state()
Let's bring it back and see:
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" }
So the real purpose of __set_state
method is to initialize an object in case someone "serialized" it with var_export
.
Why someone would need that? Objects serialized with serialize
need to be unserialized with unserialize
. But objects saved in files by var_export
could just be included because it's just a valid PHP code.
Edit:
I would not really call this method magic
(even though it's in the docs described as such) as there's nothing magical about it. PHP just assumes it's there when var_export
is called, and it must be there if you want to use whatever var_export
produced. I would say it's just a convention that it's called __set_state
- no magic there. But it's just my humble opinion.
来源:https://stackoverflow.com/questions/46441958/what-is-the-real-purpose-of-magic-method-set-state-in-php