gpt4 book ai didi

php - 与 __get_state() 之类的 __set_state() 相反?

转载 作者:可可西里 更新时间:2023-11-01 12:53:22 25 4
gpt4 key购买 nike

__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 时有效。在此示例中,我选择仅导出 namebar 而不是 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/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com