Opposite to __set_state (), how is __get_state ()?

Is there an opposite PHP function for __set_state() like __get_state() ? And I don't mean __sleep() for serialization. I want a simple function to be called after var_export() is called on an object, but before var_export() gets the data so that I can select on each object whose data will be exported. I know that there is a way to implement this with __get() and debug_backtrace() to change the data only when var_export() is called on the object. But is there an easier way?

Change It is not possible to implement this with __get() and debug_backtrace() to change data only when var_export() is called on an object because __get() not called on var_export() .

Decision

 <?php /* * @author Christian Mayer <http://fox21.at> * @link http://stackoverflow.com/q/21762276/823644 * @link https://eval.in/163041 * @link https://eval.in/163462 * @link https://eval.in/163909 * @link https://gist.github.com/TheFox/49ff6903da287c30e72f */ interface Exportable{ public function __get_state(); } function unset_with_get_state($expression){ $before = clone $expression; $classVars = array_keys(get_class_vars(get_class($before))); foreach(array_diff($classVars, $before->__get_state()) as $var){ unset($before->$var); } return $before; } function my_var_export($expression, $return = null){ $before = $expression; if($before instanceof Exportable){ $before = unset_with_get_state($expression); } return var_export($before, $return); } class Foo implements Exportable{ public $name = null; public $foo = null; public $bar = null; public function __get_state(){ // Only show 'name' and 'bar' on my_var_export(). return array('name', 'bar'); } } $a = 'hello'; my_var_export($a); print "\n"; $b = new Foo(); $b->name = 'world'; $b->foo = 'foo is foo'; $b->bar = 'bar is bar'; my_var_export($b); print "\n"; 

Of course, with your own implementation you can do everything. is there a simpler way? I mean, if there is a built-in PHP function or something like that, so you don't have to do it yourself. This solution is not very simple because you have to expand all your objects with Exportable . And this also only works when your variables are public . In this example, I chose to export only name and bar , but not foo . The PHP built-in function (e.g. __set_state() ) will be more enjoyable.

+7
object php class
source share
1 answer

You write in your question:

I need a simple function called after calling var_export (), but before var_export () gets the data

It looks like you want to accept the var_export() function and then call the adapter instead of var_export() . Then, inside the adapter, you get the data before it is (really) var_export()ed :

 function my_var_export($expression, $return = NULL) { $before = $expression; return var_export($before, $return); } $a = 'hello'; my_var_export($a); // 'hello' 

With this adapter, you can technically install what you are looking for, but it is also a prerequisite.

So, we are concerned about objects, not strings. And for these objects, the __get_state() method should be called. Since we still know what this object should be (it must be exported), we create an interface:

 interface Exportable { /** * @return static clone of $this for var_export */ public function __get_state(); } 

So how can this be implemented? One idea is to clone the real object and then modify it so that var_export does not encounter any problems with it. This cloning will save us from manipulating a specific object just for exporting it. But this is just a convention, an object that cannot be cloned can implement this __get_state() method, it might be a little harder to write an implementation.

And on the other hand, using the interface, the adapter my_var_export() can be more intelligent in how to treat $before when passing it to var_export() :

 function my_var_export($expression, $return = null) { $before = $expression instanceof Exportable ? $expression->__get_state() : $expression; return var_export($before, $return); } 

A new case has been introduced when exporting $expression requires special processing. This works as before for the expression $a = 'hello'; .

So now, to give it an edge, we need a specific type that is exportable, for example I use Foo here. For testing purposes, I give it a private property that is set only when the implementation of __get_state() was called in the accepted var_export() operation:

 class Foo implements Exportable { private $name = null; private $__get_state_called; public function __construct($name) { $this->name = (string)$name; } public function __get_state() { $before = clone $this; // or if inherited: parent::__get_state() $before->__get_state_called = true; return $before; } } 

Working example than:

 $b = new Foo('hello'); my_var_export($b); 

Which gives the result as desired:

 Foo::__set_state(array( 'name' => 'hello', '__get_state_called' => true, )) 

And that your "magic" function __get_state() , which is called before var_export() , receives data, but after calling ( my_ ) var_export() .

Adapt the var_export function to add the necessary functions. Use the interface for objects that need special handling.

Full example ( run it on the Internet ):

 <?php /* * @author hakre <http://hakre.wrodpress.com/> * @link http://stackoverflow.com/a/24228153/367456 * @link https://eval.in/163041 */ /** * Interface Exportable */ interface Exportable { /** * @return static clone of $this for var_export */ public function __get_state(); } /** * @param mixed $expression * @param bool $return (optional) * * @return void|string */ function my_var_export($expression, $return = null) { $before = $expression instanceof Exportable ? $expression->__get_state() : $expression; return var_export($before, $return); } /** * Class Foo */ class Foo implements Exportable { private $name = null; private $__get_state_called; public function __construct($name) { $this->name = (string)$name; } /** * @see Exportable * @return Foo|static */ public function __get_state() { $before = clone $this; // or if inherited: parent::__get_state() $before->__get_state_called = true; return $before; } } $a = 'hello'; my_var_export($a); echo "\n\n"; $b = new Foo('world'); my_var_export($b); 
+7
source share

All Articles