web-dev-qa-db-fra.com

Exception: la sérialisation de 'Fermeture' n'est pas autorisée

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 /.

48
TheWebs

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");
38
Baba

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);
22
Ifnot

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.

12
ArjanW

Vous devez désactiver Globals

 /**
 * @backupGlobals disabled
 */
3
Sampath Perera