Поэтому я не совсем уверен, что мне нужно будет показать вам, ребята, как бы то ни было, если вам нужно больше кода, пожалуйста, не стесняйтесь спрашивать:
Таким образом, этот метод настроит initMailer для Zend в нашем приложении:
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; }
Вы можете увидеть закрытие, которое находится внутри. Когда я запускаю какие-либо тесты, которые используют этот код, я получаю:
Exception: Serialization of 'Closure' is not allowed
и, следовательно, все тесты в связи с этим «закрытием» терпят неудачу. Поэтому я здесь прошу вас, ребята, что я должен делать.
Для выяснения вышеизложенного все делали это, говоря, что любое электронное письмо, которое мы отправляем, мы хотим хранить информацию об этом письме в папке / tmp / mail / directory в файле.
По-видимому, анонимные функции не могут быть сериализованы.
пример
$function = function () { return "ABC"; }; serialize($function); // would throw error
Из вашего кода вы используете Closure
$callback = function () // <---------------------- Issue { return 'ZendMail_' . microtime(true) . '.tmp'; };
Решение 1. Замените с нормальной функцией. Пример.
function emailCallback() { return 'ZendMail_' . microtime(true) . '.tmp'; } $callback = "emailCallback" ;
Решение 2. Косвенный вызов метода по переменной массива
Если вы посмотрите на 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 = array($this,"aMethodInYourClass");
PHP не допускает сериализации с прямым закрытием. Но вы можете использовать класс powefull, например PHP Super Closure: https://github.com/jeremeamia/super_closure
Этот класс очень прост в использовании и входит в структуру laravel для менеджера очередей.
Из документации github:
$helloWorld = new SerializableClosure(function ($name = 'World') use ($greeting) { echo "{$greeting}, {$name}!\n"; }); $serialized = serialize($helloWorld);
Как уже говорилось: закрытие, из коробки, не может быть сериализовано.
Однако, используя магические методы __sleep()
, __wakeup()
и отражение и CAN, вручную делают замыкания сериализуемыми. Подробнее см. Расширение-php-5-3-closures-with-serialization-and-reflection
Это использует отражение и функцию php eval . Обратите внимание, что это открывает возможность инъекции CODE, поэтому, пожалуйста, обратите внимание на то, что вы сериализуете.
Вы должны отключить глобальные
/** * @backupGlobals disabled */