Donc, je ne sais pas exactement ce que je devrais vous montrer, mais si vous avez besoin de plus de code, n'hésitez pas à demander:
Cette méthode va donc configurer initMailer for Zend dans notre application:
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;
}
Vous pouvez voir la fermeture qui se trouve dans po. Lorsque je lance des tests qui utilisent ce code, je reçois:
Exception: Serialization of 'Closure' is not allowed
et donc tous les tests relatifs à cette "fermeture" échouent. Je suis donc ici pour vous demander ce que je devrais faire.
Pour clarifier ce qui précède, tout ce que nous faisions était de dire que nous voulions stocker tous les courriels que nous envoyons dans un dossier du dossier/tmp/mail /.
Les fonctions apparemment anonymes ne peuvent pas être sérialisées.
Exemple
$function = function () {
return "ABC";
};
serialize($function); // would throw error
À partir de votre code, vous utilisez Closure:
$callback = function () // <---------------------- Issue
{
return 'ZendMail_' . microtime(true) . '.tmp';
};
Solution 1: à remplacer par une fonction normale
Exemple
function emailCallback() {
return 'ZendMail_' . microtime(true) . '.tmp';
}
$callback = "emailCallback" ;
Solution 2: Appel de méthode indirect par variable tableau
Si vous regardez 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 }
Vous pouvez utiliser la même approche pour envoyer le rappel
$callback = array($this,"aMethodInYourClass");
La sérialisation à fermeture directe n'est pas autorisée par PHP. Mais vous pouvez utiliser la classe powefull comme PHP Super Closure: https://github.com/jeremeamia/super_closure
Cette classe est très simple à utiliser et est intégrée au framework laravel du gestionnaire de files d'attente).
De la documentation de github:
$helloWorld = new SerializableClosure(function ($name = 'World') use ($greeting) {
echo "{$greeting}, {$name}!\n";
});
$serialized = serialize($helloWorld);
Comme déjà indiqué: les fermetures prêtes à l'emploi ne peuvent pas être sérialisées.
Cependant, en utilisant les méthodes __sleep()
, __wakeup()
magiques et la réflexion u CAN, vous pouvez manuellement rendre les fermetures sérialisables. Pour plus de détails, voir extension-php-5-3-fermetures-avec-sérialisation-et-réflexion
Cela utilise la réflexion et la fonction php eval. Notez que cela ouvre la possibilité d’injection CODE, veuillez donc noter ce que vous sérialisez.
Vous devez désactiver Globals
/**
* @backupGlobals disabled
*/