例外:不允许序列化“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 */