joomla-x/event

Joomla 事件包

安装: 195

依赖项: 1

建议者: 0

安全: 0

星标: 0

关注者: 2

分支: 9

开放问题: 0

类型:joomla-package

1.2.0 2016-03-13 19:41 UTC

README

事件包提供了构建事件系统的基础,并支持优先级监听器。

事件

示例

事件有一个名称,并且可以传输参数。

namespace MyApp;

use Joomla\Event\Event;

// Creating an Event called "onSomething".
$event = new Event('onSomething');

// Adding an argument named "foo" with value "bar".
$event->addArgument('foo', 'bar');

// Setting the "foo" argument with a new value.
$event->setArgument('foo', new \stdClass);

// Getting the "foo" argument value.
$foo = $event->getArgument('foo');

其传播可以被阻止

$event->stop();

事件监听器

事件监听器可以监听一个或多个事件。

您可以创建两种类型的监听器:使用类或闭包(匿名函数)。

函数必须将 EventInterface(或其子类)作为唯一的参数。

监听器监听与其实例方法名称匹配的事件。

namespace MyApp;

use Joomla\Event\EventInterface;

/**
 * A listener listening to content manipulation events.
 */
class ContentListener
{
	/**
	 * Listens to the onBeforeContentSave event.
	 */
	public function onBeforeContentSave(EventInterface $event)
	{
		// Do something with the event, you might want to inspect its arguments.
	}

	/**
	 * Listens to the onAfterContentSave event.
	 */
	public function onAfterContentSave(EventInterface $event)
	{

	}
}

闭包

闭包可以监听任何事件,但在将其添加到分发器(见下文)时必须声明。

namespace MyApp;

use Joomla\Event\EventInterface;

$listener = function (EventInterface $event) {
	// Do something with the event, you might want to inspect its arguments.
};

分发器

分发器是事件系统的中心点,它管理事件的注册、监听器的注册以及事件的触发。

注册对象监听器

按照上面的示例,您可以注册 ContentListener 到分发器

namespace MyApp;

use Joomla\Event\Dispatcher;

// Creating a dispatcher.
$dispatcher = new Dispatcher;

/**
 * Adding the ContentListener to the Dispatcher.
 * By default, it will be registered to all events matching it's method names.
 * So, it will be registered to the onBeforeContentSave and onAfterContentSave events.
 */
$dispatcher->addListener(new ContentListener);

如果对象包含其他不应注册的方法,您需要显式列出要注册的事件。例如

$dispatcher->addListener(
    new ContentListener,
    array(
        'onBeforeContentSave' => Priority::NORMAL,
        'onAfterContentSave' => Priority::NORMAL,
    )
);

// Alternatively, include a helper method:
$listener = new ContentListener;
$dispatcher->addListener($listener, $listener->getEvents());

注册闭包监听器

namespace MyApp;

use Joomla\Event\Dispatcher;
use Joomla\Event\Priority;

// Of course, it shouldn't be empty.
$listener = function (EventInterface $event) {
};

$dispatcher = new Dispatcher;

/**
 * Adding a Closure Listener to the Dispatcher.
 * You must specify the event name and the priority of the listener.
 * Here, we register it for the onContentSave event with a normal Priority.
 */
$dispatcher->addListener(
	$listener,
	array('onContentSave' => Priority::NORMAL)
);

如您所见,您可以为特定事件指定监听器的优先级。您也可以为“对象”监听器这样做。

过滤监听器

已弃用

监听器类可能会变得相当复杂,并可能支持除了事件处理所需之外的其他公共方法。可以使用 setListenerFilter 方法设置一个正则表达式,用于检查作为监听器添加的对象的方法名称。

// Ensure the dispatcher only registers "on*" methods.
$dispatcher->setListenerFilter('^on');

带优先级的注册

namespace MyApp;

use Joomla\Event\Dispatcher;
use Joomla\Event\Priority;

/**
 * Adding the ContentListener to the Dispatcher.
 * It will be registered with a high priority for the onBeforeContentSave, and
 * an "Above normal" priority for the onAfterContentSave event.
 */
$dispatcher->addListener(
	new ContentListener,
	array(
		'onBeforeContentSave' => Priority::HIGH,
		'onAfterContentSave' => Priority::ABOVE_NORMAL
	)
);

默认优先级是 Priority::NORMAL

当您添加未指定事件名称的“对象”监听器时,它将使用NORMAL优先级注册到所有事件。

/**
 * Here, it won't be registered to the onAfterContentSave event because
 * it is not specified.
 *
 * If you specify a priority for an Event,
 * then you must specify the priority for all Events.
 *
 * It is good pracctice to do so, it will avoid to register the listener
 * to "useless" events and by consequence save a bit of memory.
 */
$dispatcher->addListener(
	new ContentListener,
	array('onBeforeContentSave' => Priority::NORMAL)
);

如果某些监听器对给定事件的优先级相同,它们将按添加到分发器的顺序被调用。

注册事件

如果您需要自定义事件,则可以将事件注册到分发器。

namespace MyApp;

use Joomla\Event\Dispatcher;
use Joomla\Event\Event;

// Creating an event with a "foo" argument.
$event = new Event('onBeforeContentSave');
$event->setArgument('foo', 'bar');

// Registering the event to the Dispatcher.
$dispatcher = new Dispatcher;
$dispatcher->addEvent($event);

默认情况下,在触发事件时,将创建不带参数的 Event 对象。

触发事件

一旦注册了您的监听器(以及最终将事件添加到分发器),您就可以触发事件。

监听器将按照它们对该事件的优先级顺序在队列中调用。

// Triggering the onAfterSomething Event.
$dispatcher->triggerEvent('onAfterSomething');

如果您注册了一个具有 onAfterSomething 名称的事件对象,则它将传递给所有监听器,而不是默认的事件。

您还可以在触发时传递自定义事件

namespace MyApp;

use Joomla\Event\Dispatcher;
use Joomla\Event\Event;

// Creating an event called "onAfterSomething" with a "foo" argument.
$event = new Event('onAfterSomething');
$event->setArgument('foo', 'bar');

$dispatcher = new Dispatcher;

// Triggering the onAfterSomething Event.
$dispatcher->triggerEvent($event);

如果您已经使用 addEvent 添加了具有 onAfterSomething 名称的事件,则传递给 triggerEvent 方法的事件将被选择。

阻止传播

如上所述,如果您正在监听支持传播的事件,则可以停止事件传播,这是 Event 类的情况。

namespace MyApp;

use Joomla\Event\Event;

class ContentListener
{
	public function onBeforeContentSave(Event $event)
	{
		// Stopping the Event propagation.
		$event->stop();
	}
}

在停止事件传播时,队列中的下一个监听器不会被调用。

可观察的类

可观察的类依赖于分发器,并且它们可能实现了 DispatcherAwareInterface 接口。

模型类的示例

namespace MyApp;

use Joomla\Event\DispatcherAwareInterface;
use Joomla\Event\DispatcherInterface;
use Joomla\Event\Event;

class ContentModel implements DispatcherAwareInterface
{
	const ON_BEFORE_SAVE_EVENT = 'onBeforeSaveEvent';
	const ON_AFTER_SAVE_EVENT = 'onAfterSaveEvent';

	/**
	 * The underlying dispatcher.
	 *
	 * @var  DispatcherInterface
	 */
	protected $dispatcher;

	public function save()
	{
		$this->dispatcher->triggerEvent(self::ON_BEFORE_SAVE_EVENT);

		// Perform the saving.

		$this->dispatcher->triggerEvent(self::ON_AFTER_SAVE_EVENT);
	}

	/**
	 * Set the dispatcher to use.
	 *
	 * @param   DispatcherInterface  $dispatcher  The dispatcher to use.
	 *
	 * @return  DispatcherAwareInterface  This method is chainable.
	 */
	public function setDispatcher(DispatcherInterface $dispatcher)
	{
		$this->dispatcher = $dispatcher;
	}
}

不可变事件

不可变事件在实例化后不能被修改

  • 其参数不能被修改
  • 其传播不能被阻止

当您不希望监听器操作它时(它们只能检查它)很有用。

namespace MyApp;

use Joomla\Event\EventImmutable;

// Creating an immutable event called onSomething with an argument "foo" with value "bar"
$event = new EventImmutable('onSomething', array('foo' => 'bar'));

委派分发器

一个将方法委托给其他Dispatcher的调度器。这是一种实现Dispatcher不可变性的简单方法。

namespace MyApp;

use Joomla\Event\DelegatingDispatcher;
use Joomla\Event\Dispatcher;

$dispatcher = new Dispatcher;

// Here you add you listeners and your events....

// Instanciating a delegating dispatcher.
$delegatingDispatcher = new DelegatingDispatcher($dispatcher);

// Now you inject this dispatcher in your system, and it has only the triggerEvent method.

当你想确保第三方应用程序不会向Dispatcher注册或删除监听器时,这很有用。

通过Composer安装

"joomla-x/event": "3.0.*@dev"添加到您的composer.json文件中的require块,然后运行composer install

{
	"require": {
		"joomla-x/event": "3.0.*@dev"
	}
}

或者,您可以直接在命令行运行以下命令

composer require joomla-x/event "3.0.*@dev"