- android - RelativeLayout 背景可绘制重叠内容
- android - 如何链接 cpufeatures lib 以获取 native android 库?
- java - OnItemClickListener 不起作用,但 OnLongItemClickListener 在自定义 ListView 中起作用
- java - Android 文件转字符串
__set_state()
是否有一个与 __get_state()
相反的 PHP 函数?我的意思不是 __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";
当然,通过自己的实现,您可以做任何事情。使用 有更简单的方法吗?
我的意思是如果有内置的 PHP 函数或类似的东西,那么您就不必自己动手了。这个解决方案并不是很简单,因为您必须从Exportable
扩展您的所有对象。这也仅在您的变量为 public
时有效。在此示例中,我选择仅导出 name
和 bar
而不是 foo
。一个内置的 PHP 函数(如 __set_state()
是)会更好。
最佳答案
你在问题中写下:
I want a simple function which is called after var_export() is called on a object but before var_export() gets the data
这听起来像是您想采用 var_export()
函数,然后调用适配器而不是 var_export()
。然后在适配器内部你会得到数据 before 它是(真的)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()
方法。由于我们目前知道这样的对象应该是什么(它应该是可导出的),我们创建一个接口(interface):
interface Exportable {
/**
* @return static clone of $this for var_export
*/
public function __get_state();
}
那么如何实现呢?一种想法是克隆真实对象然后更改它,这样 var_export
就不会遇到任何问题。这种克隆将使我们免于操作具体对象只是为了导出它。但这只是一个约定,一个不能被克隆的对象也可以实现这个__get_state()
方法,到时候写实现可能会稍微复杂一些。
另一方面,在接口(interface)的帮助下,适配器 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);
}
只是插入了一个Exportable $expression
需要特殊处理的新案例。对于 $a = 'hello';
表达式,这与以前一样有效。
现在开始吧,我们需要一个Exportable 的具体类型,示例性的我在这里使用了Foo。出于测试目的,我给它一个私有(private)属性,只有在 __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()
被调用。
调整函数 var_export
以添加您需要的功能。为需要特殊处理的对象使用接口(interface)。
完整示例 ( 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);
关于php - 与 __get_state() 之类的 __set_state() 相反?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21762276/
__set_state() 是否有一个与 __get_state() 相反的 PHP 函数?我的意思不是 __sleep() 用于序列化。我想要一个简单的函数,它在对象上调用 var_export()
我是一名优秀的程序员,十分优秀!