例外:不允许序列化“closures”
所以我不确定我要告诉你们什么,如果你需要更多的代码,请不要犹豫,问问:
所以这个方法将在我们的应用程序中为Zend设置initMailer:
protected function _initMailer() { if ('testing' !== APPLICATION_ENV) { $this->bootstrap('Config'); $options = $this->getOptions(); $mail = new Zend_Application_Resource_Mail($options['mail']); }elseif ('testing' === APPLICATION_ENV) { //change the mail transport only if dev or test if (APPLICATION_ENV <> 'production') { $callback = function() { return 'ZendMail_' . microtime(true) .'.tmp'; }; $mail = new Zend_Mail_Transport_File( array('path' => '/tmp/mail/', 'callback'=>$callback ) ); Zend_Mail::setDefaultTransport($mail); } } return $mail; }
你可以看到与之相关的闭包。当我运行任何使用这个代码的testing时,我得到:
Exception: Serialization of 'Closure' is not allowed
因此所有关于这个“封闭”的testing都失败了。 所以我在这里问你们我该怎么做。
为了澄清上述情况,所有人都在说我们发送的任何电子邮件,我们希望将有关该电子邮件的信息存储在文件中/ tmp / mail /目录中的文件夹中。
显然匿名函数不能被序列化。
例
$function = function () { return "ABC"; }; serialize($function); // would throw error
从你的代码中使用Closure
$callback = function () // <---------------------- Issue { return 'ZendMail_' . microtime(true) . '.tmp'; };
解决scheme1:用一个正常的函数replace例子
function emailCallback() { return 'ZendMail_' . microtime(true) . '.tmp'; } $callback = "emailCallback" ;
解决scheme2:通过数组variables间接调用方法
如果您查看http://docs.mnkras.com/libraries_23rdparty_2_zend_2_mail_2_transport_2file_8php_source.html
public function __construct($options = null) 63 { 64 if ($options instanceof Zend_Config) { 65 $options = $options->toArray(); 66 } elseif (!is_array($options)) { 67 $options = array(); 68 } 69 70 // Making sure we have some defaults to work with 71 if (!isset($options['path'])) { 72 $options['path'] = sys_get_temp_dir(); 73 } 74 if (!isset($options['callback'])) { 75 $options['callback'] = array($this, 'defaultCallback'); <- here 76 } 77 78 $this->setOptions($options); 79 }
您可以使用相同的方法发送callback
$callback = array($this,"aMethodInYourClass");
PHP不允许直接closures序列化。 但是你可以像使用PHP Super Closure一样使用powefull类: https : //github.com/jeremeamia/super_closure
这个类非常简单易用,并被捆绑到队列pipe理器的laravel框架中。
从github文档:
$helloWorld = new SerializableClosure(function ($name = 'World') use ($greeting) { echo "{$greeting}, {$name}!\n"; }); $serialized = serialize($helloWorld);
正如已经说过的那样:开箱即用的closures不能被序列化。
但是,使用__sleep()
, __wakeup()
魔法和reflection手段可以手动使闭包可序列化。 有关更多详细信息,请参阅扩展php-5-3-closures-with-serialization-and-reflection
这使得reflection和php函数使用eval 。 请注意,这会打开代码注入的可能性,所以请注意您正在序列化的内容。
你必须禁用全局
/** * @backupGlobals disabled */