当我尝试序列化一个包含闭包成员的对象时,会抛出异常。 为了避免包括闭包在内的成员序列化,我尝试了以下方法:
function __sleep(){
$ref = new ReflectionClass($this);
$props = $ref->getProperties();
foreach ($props as $prop){
$name = $prop->name;
if (is_callable($this->$name)===false){
$dream[] = $prop->name;
}
}
return $dream;
}
不幸的是,这不起作用。有没有更好的方法来检测属性是否为闭包。
编辑:我通过让闭包知道是否序列化来解决我的问题
为此,我正在包装闭包本身。这是一个例子:
/**
* Wrapper-class to prevent closure to be serialized.
*/
class WrappedClosure {
private $closure = NULL;
protected $reflection = NULL;
public function __construct($function){
if ( ! $function instanceOf Closure)
throw new InvalidArgumentException();
$this->closure = $function;
$this->reflection = new ReflectionFunction($function);
}
/**
* When the instance is invoked, redirect invocation to closure.
*/
public function __invoke(){
$args = func_get_args();
return $this->reflection->invokeArgs($args);
}
// do nothing on serialization
public function __sleep(){}
// do nothing on serialization
public function __wakeup(){}
}
// Assigning a wrapped closure to a member
$myObject->memberHoldingAClosure =
// Wrapping the closure
new WrappedClosure(
function (){
echo "I'am the inner closure.";
}
)
);
// the serialization doesn't throw an exception anymore
serialize($myObject);
最佳答案
对我来说很好:
class foo {
protected $param = 'value';
protected $closure = null;
public function __construct() {
$this->closure = function(){
return 123;
};
}
public function __sleep() {
$serializable = array();
foreach ( $this as $paramName => $paramValue ) {
if ( !is_string($paramValue) && !is_array($paramValue) && is_callable($paramValue) ) {
continue;
}
$serializable[] = $paramName;
}
return $serializable;
}
}
$foo = new foo();
echo serialize($foo);
关于检查值是否是 Closure
类的实例(来自手册):
Anonymous functions are currently implemented using the Closure class. This is an implementation detail and should not be relied upon.
因此,我会将 is_closure($value)
函数实现为 return !is_string($value) && !is_array($value) && is_callable($value)
而不是return $value instanceof Closure
并希望有一天 PHP 开发人员会添加原生的 is_closure()
函数。
关于php - 检测 __sleep 中的关闭以防止其序列化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5580142/