与__get_state()相反的__set_state()相反?

The*_*Fox 7 php class object

是否有相反的PHP函数__set_state()__get_state()?而且我不是指__sleep()序列化.我想要一个简单的函数,var_export()在对象上调用后调用,但在var_export()获取数据之前,我可以在每个对象上选择要导出的数据.我知道有一种方法可以实现这个,__get()并且debug_backtrace()只有在var_export()对象上调用时才修改数据. 但是有更简单的方法吗?

编辑:有没有办法跟来实现这个__get()debug_backtrace()修改数据,只有当var_export()被称为对象,因为__get()不叫上var_export().

方案:

<?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";
Run Code Online (Sandbox Code Playgroud)

当然,通过自己的实现,您可以做任何事情.随着is there a simpler way?我的意思是,如果有一个内置的PHP函数或类似的东西,所以你不必自己做.这个解决方案并不容易,因为你必须扩展所有对象Exportable.这也适用于您的变量public.在这个例子中,我选用仅导出namebar,但不会foo.内置的PHP函数(比如__set_state()是)会更好.

hak*_*kre 7

你写下你的问题:

我想要一个简单的函数,在对象上调用var_export()之后但在var_export()获取数据之前调用

这听起来像你想要采用该var_export()功能然后调用适配器而不是var_export().然后在适配器内部,你会得到的数据之前,它是(真的)var_export()ed:

function my_var_export($expression, $return = NULL) {
    $before = $expression;
    return var_export($before, $return);
}

$a = 'hello';
my_var_export($a); // 'hello'
Run Code Online (Sandbox Code Playgroud)

使用此适配器,您在技术上能够确定您正在寻找的内容,但这也是前提条件.

所以我们关心的是对象,而不是字符串.对于那些对象,__get_state()应该调用该方法.到目前为止,我们知道这样的对象应该是什么(它应该是可导出的),我们创建一个接口:

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

那怎么能实现呢?一个想法是克隆真实对象,然后更改它,以便var_export不会遇到任何问题.这种克隆将使我们无需操纵具体对象即可将其导出.但这只是一个约定,一个无法克隆的对象也可以实现这个__get_state()方法,那么编写实现可能会稍微复杂一些.

另一方面,在界面的帮助下,适配器my_var_export()可以更加智能化,如何$before将其传递给var_export():

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

    return var_export($before, $return);
}
Run Code Online (Sandbox Code Playgroud)

只是插入了Exportable $expression需要特殊处理的新案例.这与$a = 'hello';表达式一样.

所以现在要试一试,我们需要一个可导出的具体类型,我在这里使用Foo.出于测试目的,我给它一个私有属性,只有在__get_state()已采用的var_export()操作中调用了实现时才设置:

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;
    }
}
Run Code Online (Sandbox Code Playgroud)

工作的例子是:

$b = new Foo('hello');
my_var_export($b);
Run Code Online (Sandbox Code Playgroud)

这给出了想要的输出:

Foo::__set_state(array(
   'name' => 'hello',
   '__get_state_called' => true,
))
Run Code Online (Sandbox Code Playgroud)

__get_state()这是 var_export() 获取数据之前调用的"魔术"函数,但调用after(my_)之后var_export().

调整功能var_export以添加所需的功能.使用接口来处理需要特殊处理的对象.

完整示例(在线运行):

<?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);
Run Code Online (Sandbox Code Playgroud)