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

时间:2014-02-13 18:14:15

标签: php class object

__set_state()之类的__get_state()是否有相反的PHP函数?我并不是说__sleep()用于序列化。我想要一个简单的函数,在对象上调用var_export()之后但在var_export()获取数据之前调用,这样我就可以在每个对象上选择要导出的数据。 我知道有一种方法可以通过__get()debug_backtrace()来实现这一点,只有在对象上调用var_export()时才能修改数据。但是有一个更简单的方法吗?方式是什么?

修改:无法通过__get()debug_backtrace()实现此操作,仅在对象上调用var_export()时修改数据,因为{{ 1 {}未在__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"; 我的意思是,如果有一个内置的PHP函数或类似的东西,所以你不必自己做。此解决方案并非真正 easy ,因为您必须从is there a simpler way?扩展所有对象。这也适用于您的变量为Exportable的情况。在此示例中,我选择仅导出publicname,但不导出bar。内置的PHP函数(如foo)会更好。

1 个答案:

答案 0 :(得分: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'

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

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

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

那怎么能实现呢?一个想法是克隆真实对象,然后更改它,以便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);
}

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

所以现在要试一试,我们需要一个具体类型 Exportable ,示例我在这里使用 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;
    }
}

工作示例比:

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

根据需要提供输出:

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

这是你的“神奇”功能__get_state(),在 var_export()获取数据之前称为,但之后my_var_export()被称为。{/ p>

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

完整示例(run it online):

<?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);