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',
            ));
        }
    }
}

监听事件

在引导期间,我们将侦听器附加到EventManagerinside 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 回答