Расширение возможностей плагинов
# События
Вы можете добавлять или изменять функциональные возможности плагинов при помощи Событий.
# Подписка на события
Наиболее подходящее место для подписки на события - метод boot()
в файле регистрации плагина. Например, если Вы хотите добавить нового пользователя в список для рассылки, используйте глобальное событие rainlab.user.register:
public function boot()
{
Event::listen('rainlab.user.register', function($user) {
// Code to register $user->email to mailing list
});
}
Вы также можете расширить конструктор модели и использовать локальное событие.
User::extend(function($model) {
$model->bindEvent('user.register', function() use ($model) {
// Code to register $model->email to mailing list
});
});
# Объявление событий
Вы можете объявлять событие глобальным или локальным. Пример объявления глобального события:
Event::fire('acme.blog.beforePost', ['first parameter', 'second parameter']);
Пример локального события:
$this->fireEvent('blog.beforePost', ['first parameter', 'second parameter']);
Примечание: Хорошей практикой является размещение локального события перед глобальным событием из-за того, что локальные события имеют больший приоритет.
После подписки на событие, параметры будут доступны в методе обработчика. Например:
// Global
Event::listen('acme.blog.beforePost', function($param1, $param2) {
echo 'Parameters: ' . $param1 . ' ' . $param2;
});
// Local
$this->bindEvent('blog.beforePost', function($param1, $param2) {
echo 'Parameters: ' . $param1 . ' ' . $param2;
});
# События в административной части сайта
Вы можете использовать события в административной части сайта, используя метод fireViewEvent()
.
Добавьте следующий код в файл с представлением:
<div class="footer-area-extension">
<?= $this->fireViewEvent('backend.auth.extendSigninView') ?>
</div>
Он позволит другим плагинам внедрять HTML-код в эту область.
Event::listen('backend.auth.extendSigninView', function($controller) {
return '<a href="#">Sign in with Google!</a>';
});
Примечание: Первым параметром в обработчике события всегда будет вызывающий объект (контроллер).
Приведенный выше пример отобразит следующую разметку:
<div class="footer-area-extension">
<a href="#">Sign in with Google!</a>
</div>
# Примеры
Ниже приведены некоторые примеры того, как могут быть использованы события.
# Пользователь
В этом примере показано, как можно изменить атрибут $model->foo
модели User
.
class Plugin extends PluginBase
{
[...]
public function boot()
{
// Local event hook that affects all users
User::extend(function($model) {
$model->bindEvent('model.getAttribute', function($attribute, $value) {
if ($attribute == 'foo') {
return 'bar';
}
});
});
// Double event hook that affects user #2 only
User::extend(function($model) {
$model->bindEvent('model.afterFetch', function() use ($model) {
if ($model->id != 2) {
return;
}
$model->bindEvent('model.getAttribute', function($attribute, $value) {
if ($attribute == 'foo') {
return 'bar';
}
});
});
});
}
}
# Форма
В этом примере показано, как можно добавить и удалить поле из формы редактирования пользователя.
class Plugin extends PluginBase
{
[...]
public function boot()
{
// Extend all backend form usage
Event::listen('backend.form.extendFields', function($widget) {
// Only for the User controller
if (!$widget->getController() instanceof \RainLab\User\Controllers\Users) {
return;
}
// Only for the User model
if (!$widget->model instanceof \RainLab\User\Models\User) {
return;
}
// Add an extra birthday field
$widget->addFields([
'birthday' => [
'label' => 'Birthday',
'comment' => 'Select the users birthday',
'type' => 'datepicker'
]
]);
// Remove a Surname field
$widget->removeField('surname');
});
}
}
Не забудьте добавить
use Event
в верхнюю часть файла класса.
# Список
В этом примере показано, как можно добавить и удалить столбец из списка с пользователями.
class Plugin extends PluginBase
{
[...]
public function boot()
{
// Extend all backend list usage
Event::listen('backend.list.extendColumns', function($widget) {
// Only for the User controller
if (!$widget->getController() instanceof \RainLab\User\Controllers\Users) {
return;
}
// Only for the User model
if (!$widget->model instanceof \RainLab\User\Models\User) {
return;
}
// Add an extra birthday column
$widget->addColumns([
'birthday' => [
'label' => 'Birthday'
]
]);
// Remove a Surname column
$widget->removeColumn('surname');
});
}
}
Не забудьте добавить
use Event
в верхнюю часть файла класса.
# Компонент
В этом примере показано, как можно добавить новое глобальное событие rainlab.forum.topic.post
и локальное событие topic.post
в компонент Topic
.
class Topic extends ComponentBase
{
public function onPost()
{
[...]
/*
* Extensibility
*/
Event::fire('rainlab.forum.topic.post', [$this, $post, $postUrl]);
$this->fireEvent('topic.post', [$post, $postUrl]);
}
}
Пример добавления записи в журнал при загрузке страницы с компонентом Topic
:
[topic]
slug = "{{ :slug }}"
==
function onInit()
{
$this['topic']->bindEvent('topic.post', function($post, $postUrl) {
trace_log('A post has been submitted at '.$postUrl);
});
}
# Меню
В этом примере показано, как можно заменить название элемента меню в административной части сайта.
class Plugin extends PluginBase
{
[...]
public function boot()
{
Event::listen('backend.menu.extendItems', function($manager) {
$manager->addMainMenuItems('October.Cms', [
'cms' => [
'label' => '...'
]
]);
$manager->addSideMenuItems('October.Cms', 'cms', [
'pages' => [
'label' => '...'
]
]);
});
}
}
В этом примере показано, как можно удалить элемент меню в административной части сайта.
Event::listen('backend.menu.extendItems', function($manager) {
$manager->removeMainMenuItem('October.Cms', 'cms');
$manager->removeSideMenuItem('October.Cms', 'cms', 'pages');
});