62

だから私はあなたたちに何を見せなければならないのか正確にはわかりませんが、もっとコードが必要な場合は遠慮なく質問してください:

したがって、このメソッドは、アプリケーションで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;
}

にあるクロージャを確認できます。このコードを使用するテストを実行すると、次のようになります。

Exception: Serialization of 'Closure' is not allowed 

したがって、この「閉鎖」に関連するすべてのテストは失敗します。だから私はここで皆さんに私が何をすべきかを尋ねています。

上記を明確にするために、私たちが送信するすべての電子メールは、ファイル内の/ tmp /mail/ディレクトリ内のフォルダにその電子メールに関する情報を保存したいと言っています。

4

5 に答える 5

42

どうやら無名関数はシリアル化できません。

$function = function () {
    return "ABC";
};
serialize($function); // would throw error

クロージャーを使用しているコードから:

$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");
于 2012-12-05T23:21:53.813 に答える
27

PHPでは、直接クロージャーのシリアル化は許可されていません。ただし、PHP Super Closureのようなpowefullクラスを使用できます:https ://github.com/jeremeamia/super_closure

このクラスは非常に使いやすく、キューマネージャーのlaravelフレームワークにバンドルされています。

githubのドキュメントから:

$helloWorld = new SerializableClosure(function ($name = 'World') use ($greeting) {
    echo "{$greeting}, {$name}!\n";
});

$serialized = serialize($helloWorld);
于 2013-11-01T15:47:22.697 に答える
12

すでに述べたように、クロージャーは、箱から出してすぐにシリアル化することはできません。

ただし、マジックメソッドとリフレクションを使用する__sleep()と、__wakeup()クロージャを手動でシリアル化できます。詳細については、extending-php-5-3-closures-with-serialization-and-reflectionを参照してください。

これは、リフレクションとphp関数evalを利用します。これによりCODEインジェクションの可能性が開かれることに注意してください。したがって、シリアル化する内容に注意してください。

于 2013-02-11T10:09:43.333 に答える
2

グローバルを無効にする必要があります

 /**
 * @backupGlobals disabled
 */
于 2017-09-01T09:38:36.893 に答える
-1

これは実験的なものであり、安全ではありません。無効にできるeval()を使用する必要があるなどのいくつかのリスクがあります。最良の方法は、ヒアドキュメントの例でシリアル化されたスクリプトを作成することです。

$code = <<<CODE
 <?php
class \$gen_class_{$user}{
 ...
}
CODE;

コードをシリアル化するか、拡張子「.class.php」を付けて記述することで、コードをより簡単に使用できます。スクリプトを簡単に呼び出して永続化することができます。

https://3v4l.org/jpHm9 UPDATE PHP 8

<?php

function closure_to_str($func)
{
    $refl = new \ReflectionFunction($func); // get reflection object
    $path = $refl->getFileName();  // absolute path of php file
    $begn = $refl->getStartLine(); // have to `-1` for array index
    $endn = $refl->getEndLine();
    $dlim = PHP_EOL;
    $list = explode($dlim, file_get_contents($path));         // lines of php-file source
    $list = array_slice($list, ($begn-1), ($endn-($begn-1))); // lines of closure definition
    $last = (count($list)-1); // last line number

    if((substr_count($list[0],'function')>1)|| (substr_count($list[0],'{')>1) || (substr_count($list[$last],'}')>1))
    { throw new \Exception("Too complex context definition in: `$path`. Check lines: $begn & $endn."); }

    $list[0] = ('function'.explode('function',$list[0])[1]);
    $list[$last] = (explode('}',$list[$last])[0].'}');


    return implode($dlim,$list);
}

$test = 10;
$dog2 = function($var=0) use ($test){ 
    $var = 10;
    echo $var . PHP_EOL;
    return $test . $var;
};

echo closure_to_str($dog2)."\n\n";

文字列を返す

function($var=0) use ($test){ 
    $var = 10;
    echo $var . PHP_EOL;
    return $test . $var;
}
于 2021-11-11T21:28:32.777 に答える