是否有相反的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.在这个例子中,我选用仅导出name和bar,但不会foo.内置的PHP函数(比如__set_state()是)会更好.
你写下你的问题:
我想要一个简单的函数,在对象上调用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)