3.phpBB Extension Events and Listeners
介绍
phpBB 3.1引入了整个代码库和模板文件中的事件系统,允许扩展使用侦听器来添加功能,注入代码和写改现有的功能和行为。
本教程将介绍如何使用事件和侦听器:
Template Events & ListenersPHP Core Events & ListenersTemplate Events & Listeners
模板事件允许扩展将代码注入到模板文件中。 事件可以在phpBB样式的整个模板结构中找到,提供多个有用的注入点。 典型的模板事件如下所示:
<!-- EVENT event_name_and_position -->
也可以看看
在我们的维基中查看模板事件的完整列表。https://wiki.phpbb.com/Event_List#Template_Events
Listening for an event
要订阅模板事件,我们必须创建一个监听器,一个与我们想要使用的模板事件的标识符完全相同的模板文件,并将其放在样式模板文件夹的事件/子目录中。
例如,我们将使用overall_header_navigation_prepend事件在板的导航栏中的现有链接之前添加一个新链接。 此活动的听众将是:
acme/demo/styles/prosilver/template/event/overall_header_navigation_prepend.html
小提示
如果您希望所有样式使用模板侦听器,则应将其放在all / style目录中,例如供应商/ extname/风格/所有/模板/事件/。 这有助于防止代码重复并简化样式文件管理。
对于必须根据每种风格定制的模板文件,应该使用prosilver和subsilver2目录。 同样,如果第三方风格需要额外的自定义来维护兼容性,那么该样式的文件夹应该包含在这些模板文件中。
要添加ACP模板侦听器,请将这些文件放在vendor/extname/adm/style/event /中。
在模板侦听器中,我们将创建一个导航栏链接。 这包括一个简单的列表元素,具有链接和描述:
{L_DEMO_PAGE}
</li>一旦创建了模板侦听器,您应该能够看到该板的导航栏中的新链接,其中包含FAQ链接的图标和文本DEMO_PAGE。 我们将在下一节中修正链接文本。
小提示
如果链接没有出现,您可能需要从ACP的主页上清除板缓存。 您还可以在config.php文件中启用DEBUG_MODE,这将强制模板引擎始终在呈现页面时查找模板侦听器。
重要的是要明白,当phpBB编译模板时,目前还没有确定优先级的系统,其中来自不同扩展名的模板侦听器被编译为同一个事件。 在极少数情况下,一些扩展可能会导致冲突,在这种情况下,建议是扩展作者为了冲突的模板侦听器而合作解决方案。
PHP Core Events & Listeners
事件允许扩展在核心phpBB代码中的许多位置执行代码,而不修改任何代码。 这样扩展可以轻松添加功能,删除功能或修改行为,同时保持兼容性和简单的更新过程。
也可以看看
在我们的Wiki中查看支持的PHP事件的完整列表。https://wiki.phpbb.com/Event_List
The event listener
在上一节中,我们创建了一个模板侦听器,它将Acme Demo扩展的链接添加到phpBB的导航栏。我们现在将使用PHP事件加载包含DEMO_PAGE语言密钥的语言文件,以便我们的导航栏链接将显示正确的文本。
为此,我们需要创建一个PHP事件侦听器类(a.k.a. subscriber class)。该类包括一组侦听器方法,每个方法都可以在phpBB的代码库中订阅PHP事件。侦听器类必须在扩展目录的事件/子目录中创建,否则它将无法正常工作。它还必须符合以下要求:
遵循扩展类名称 - 间距约定:vendor \ extname \ event \ subscribername.php。
实现Symfony的Symfony \ Component \ EventDispatcher \ EventSubscriberInterface接口。
使用静态方法getSubscribedEvents()将侦听器中的方法预订为特定事件,其中的键包含事件名称,其值包含侦听器函数名称。
在Acme Demo扩展中,我们要加载我们的语言文件到处。因此,我们将订阅一个监听器函数到phpBB的core.user_setup事件:
那么上面的main_listener.php类是什么呢?
getSubscribedEvents()方法将我们的侦听器函数load_language_on_setup()订阅到名为core.user_setup的事件。 这意味着当这个事件发生时,我们的函数将执行。
小提示
您可以使用数组为单个事件分配多个侦听器函数:
core.user_setup=> array(array(foo_method),array(bar_method))
load_language_on_setup()监听器方法只是将语言文件添加到phpBB的语言数据数组中。 一般来说,一个监听器只是一个在用户类中的public函数,在getSubscribedEvents()返回的数组中引用。 它需要一个参数$ event。 此参数允许您从核心代码访问和修改给予事件的变量。 在这种情况下,我们通过添加Acme Demo的语言文件来修改lang_set_ext变量。
注意
请注意,lang_set_ext事件变量首先如何通过将其分配给局部变量进行复制,然后进行修改,然后将其复制。 此快捷方式不起作用:$ event [foo] [bar] = $ baz; 这是因为事件变量是重载的,这是PHP中的限制。
Registering the listener
要使phpBB自动加载并执行我们的事件侦听器类,我们需要为它创建一个服务定义。 这是通过在扩展中创建一个config / services.yml文件完成的:
警告
YAML文件缩进敏感。 它们需要每个缩进的缩进大小为4个空格,不要使用制表符。
第一行告诉phpBB正在注册服务列表。 在下一行,我们指定服务的名称,这是在这种情况下为我们的事件侦听器。
重要
服务名称必须以您的供应商和分机名称为前缀。
类属性必须包含正在注册的服务的名称空间和类名。 名称空间取决于文件的位置,在ext /目录中。 因此,文件ext / acme / demo / event / main_listener.php具有命名空间acme \ demo \ event和类名main_listener。 因此,该类的全名是acme \ demo \ event \ main_listener,这是我们需要在此处指定的。
tags属性告诉phpBB该服务是一个事件监听器。
一旦服务YAML文件被创建(或修改),phpBB的缓存需要被清除。 在ACP中清除缓存后,导航栏中链接的描述现在应显示Demo而不是DEMO_PAGE。
注意
phpBB的核心PHP和模板文件已经准备好了几十个事件位置。 但是,如果没有您的扩展可能需要的事件,phpBB开发团队欢迎在区域http://51.com事件请求论坛上的事件请求。
Prioritising event listeners (optional)
有时不同的扩展可能在竞争使用相同的PHP核心事件时遇到问题。 在尝试解决这些问题时,扩展开发人员可能希望将其扩展优先于其他人,以便在其他扩展之前触发扩展。
在这种情况下,getSubscribedEvents()方法提供了一个参数来设置事件侦听器方法的优先级。 例如:
在此示例中,$ priority是一个整数,其值默认为0.将此整数设置为更高的值等于更重第一行告诉phpBB正在注册服务列表。 在下一行,我们指定服务的名称,这是在这种情况下为我们的事件侦听器。
重要
服务名称必须以您的供应商和分机名称为前缀。
类属性必须包含正在注册的服务的名称空间和类名。 名称空间取决于文件的位置,在ext /目录中。 因此,文件ext / acme / demo / event / main_listener.php具有命名空间acme \ demo \ event和类名main_listener。 因此,该类的全名是acme \ demo \ event \ main_listener,这是我们需要在此处指定的。
tags属性告诉phpBB该服务是一个事件监听器。
一旦服务YAML文件被创建(或修改),phpBB的缓存需要被清除。 在ACP中清除缓存后,导航栏中链接的描述现在应显示Demo而不是DEMO_PAGE。
注意
phpB要,因此该侦听器将比其他订阅此事件的触发器早。
我们现在已经使用事件和监听器来修改phpBB,并在导航栏中插入一个很好的链接。 但是,该链接仍然没有工作。 继续阅读下一节,了解如何使用控制器和路由,使我们的导航栏链接打开自定义的面向用户的页面。