1

moduleMailのサービス構成内に配置した非常に単純なクラスがあります。

'factories' => array(
    'mailer' => function (ServiceLocatorInterface $sl) {
        return new \Project\Mail\Mailer();
    }
)

Mailer使用しEventManagerてイベントをトリガーします。メールの送信に失敗したときにエラーをログに記録するリスナー クラスをアタッチしたいのですが、新しいリスナーをアタッチするたびに変更せずMailerにそうしたいと考えています。Mailer

Mailer他のモジュールからリスナーをアタッチできるようにクラスを設定するにはどうすればよいですか?

4

2 に答える 2

1

Mailer最初に、「メールの送信に失敗した」とはどういう意味かを特定する必要があります。クラス内でこの条件を確認できる場合は、対応するイベントまたは類似のイベントMailerをトリガーする必要があります。mail.error

次に、リスナーを のEventManager内部にアタッチして、このイベントMailerをリッスンし、エラーをログに記録する必要があります。mail.error

内のトリガーエラーMailer

Mailerクラスが次のようになっているとしましょう。

<?php
namespace Project\Mail;

class Mailer
{
    const EVENT_MAIL_ERROR = 'mail.error';

    protected $events;

    public function setEventManager(EventManagerInterface $events)
    {
        $this->events = $events;
        return $this;
    }

    public function getEventManager()
    {
        if ($this->events === null)
        {
            $this->setEventManager(new EventManager);
        }
        return $this->events;
    }

    public function send(MessageInterface $msg)
    {
        // try sending the message. uh-oh we failed!
        if ($someErrorCondition)
        {
            $this->getEventManager()->trigger(self::EVENT_MAIL_ERROR, $this, array(
                'custom-param' => 'failure reason',
            ));
        }
    }
}

イベントのリッスン

ブートストラップ中に、リスナーをEventManagerwithinにアタッチしますMailer

<?php
namespace FooBar;

use Zend\EventManager\Event;
use Zend\Mvc\MvcEvent;

class Module
{
    public function onBootstrap(MvcEvent $event)
    {
        $application = $event->getApplication();
        $services = $application->getServiceManager();
        $mailer = $services->get('Mailer');

        $mailer->getEventManager()->attach(Mailer::EVENT_MAIL_ERROR, function(Event $event)
        {
            $param = $event->getParam('custom-param');
            // log the error
        });
    }
}

実装の詳細については、 EventManagerのドキュメントを参照してください。

これで問題が解決することを願っています!

于 2013-04-18T20:19:01.443 に答える
0

イベントをトリガーするクラスで何も設定する必要はありません。イベントをリッスンするだけで済みます。

@ user2257808 の回答は機能しますが、サービス マネージャーからメーラーをフェッチする行為により、アプリケーションの残りの部分でインスタンスが必要ない場合でもインスタンスが作成されるため、最も効率的な方法ではありません。

より良いアプローチは、イベントがトリガーされた場合に通知される共有イベント マネージャーにリスナーをアタッチすることです。

それを行うには、他の答えと非常によく似ています

public function onBootstrap(MvcEvent $event)
{
    $sharedEvents = $event->getApplication()->getEventManager()->getSharedManager();
    // listen to the 'someMailEvent' when triggered by the mailer
    $sharedEvents->attach('Project\Mail\Mailer', 'someMailEvent', function($e) {
         // do something for someMailEvent
    });
}

これで、メーラーが使用可能であることを心配する必要はありませんが、使用可能である場合は、リスナーがそれを取得するイベントをトリガーします。

于 2013-04-19T13:31:35.440 に答える