Разработчики обычно придерживаются новой CMS из-за ее простоты и расширяемости. OctoberCMS представляет собой возвращение к основам CMS и предоставляет приятный опыт как для разработчиков, так и для пользователей. В этой статье я собираюсь продемонстрировать некоторые аспекты CMS, которые делают его расширяемым, и мы также попробуем простой плагин для расширения функциональности другого плагина.
Вступление
Каждая CMS имеет систему плагинов для расширения функциональности платформы, и мы измеряем расширяемость тем, насколько глубоко мы можем проникнуть во внутреннюю работу CMS. Однако здесь мы говорим не только о CMS, но и о плагинах!
Если вы создаете плагин, вы должны убедиться, что другие разработчики могут изменить биты вашей функциональности. Например, у нас есть плагин для блога, и пользователь может опубликовать сообщение, выбрав его в списке. Было бы неплохо запустить событие, сообщающее, что опубликовано новое сообщение, и другой разработчик может подключиться к этому событию и уведомить об этом подписанных пользователей по электронной почте!
class Posts extends Controller { public function index_onPublish() { if (($checkedIds = post('checked')) && is_array($checkedIds) && count($checkedIds)) { foreach ($checkedIds as $postId) { if ((!$post = Post::find($postId)) || !$post->canEdit($this->user)) continue; $post->publish(); Event::fire('rainlab.blog.posts.published', [$post]); } Flash::success('Successfully published those posts.'); } return $this->listRefresh(); } }
Другой разработчик может прослушать это событие, чтобы что-то сделать с опубликованным постом.
Event::listen('rainlab.blog.posts.published', function($post) { User::subscribedTo($post).each(function($user) use($post) { Mail::send('emails.notifications.post-published', ['user' => $user, 'post' => $post], function($message) use($user, $post) { $message->from('[email protected]', 'New post by ' . $user->name); $message->to($user->email); }); }); });
В основном мы будем использовать события для подключения к различным частям цикла запроса. Давайте начнем с конкретного примера, чтобы прояснить ситуацию.
Плагин для блога Rainlab
Если вы некоторое время пользовались OctoberCMS, вы должны знать плагин Rainlab Blog. Он позволяет добавлять сообщения и прикреплять их к категориям в бэкэнде, а также отображать их в интерфейсе с помощью компонентов.
На странице списка сообщений у нас есть возможность удалять сообщения. Но что, если мы хотим удалить их? Давайте посмотрим, сможем ли мы это сделать, и узнаем больше о расширяемости OctoberCMS.
Создание нового плагина
Давайте создадим новый плагин для нашей демонстрации с помощью вспомогательной команды scaffolding и обновим информацию о плагине в файле Plugin.php
.
php artisan create:plugin rafie.blogplus
Расширение схемы базы данных
Первое, что приходит на ум при разговоре о мягком удалении, — это deleted_at
поля deleted_at
который должен присутствовать в БД.
Создайте новый файл с именем create_posts_deleted_at_field.php
в blogplus/updates
и обновите файл version.yaml
.
// updates/version.yaml 1.0.1: - First version of blogplus. - create_posts_deleted_at_field.php
// updates/create_posts_deleted_at_field.php class CreatePostsDeletedAtField extends Migration { public function up() { Schema::table('rainlab_blog_posts', function ($table) { $table->timestamp('deleted_at') ->default(null) ->nullable(); }); } public function down() { Schema::table('rainlab_blog_posts', function ($table) { $table->dropColumn('deleted_at'); }); } }
по// updates/create_posts_deleted_at_field.php class CreatePostsDeletedAtField extends Migration { public function up() { Schema::table('rainlab_blog_posts', function ($table) { $table->timestamp('deleted_at') ->default(null) ->nullable(); }); } public function down() { Schema::table('rainlab_blog_posts', function ($table) { $table->dropColumn('deleted_at'); }); } }
Класс миграции изменит таблицу rainlab_blog_posts
и добавит наш столбец deleted_at
с нулевым значением по умолчанию. Не забудьте запустить php artisan plugin:refresh rafie.blogplus
чтобы изменения вступили в силу.
Расширение списка сообщений
Далее мы должны добавить наше поле в виде столбца для отображения в списке. OctoberCMS предоставляет нам событие для подключения и изменения текущего отображаемого виджета (внутренний список считается виджетом).
Event::listen('backend.list.extendColumns', function ($widget) { // Only for the Posts controller if (( ! $widget->getController() instanceof \Rainlab\Blog\Controllers\Posts)) { return; } $widget->addColumns([ 'deleted_at' => [ 'label' => 'Deleted', 'type' => 'date' ] ]); });
Примечание : приведенный выше код должен быть размещен внутри метода Plugin@boot
.
У нас есть оператор if, чтобы предотвратить выполнение нашего кода на каждой странице, затем мы добавляем новый столбец в виджет списка, и мы также можем удалить любые существующие, используя метод removeColumn
. Проверьте документацию для списка доступных опций столбца .
Расширение фильтра
Панель в верхней части списка сообщений позволяет пользователю фильтровать список по дате, категории и т. Д. В нашем случае нам нужен фильтр для отображения / скрытия потерянных сообщений.
// plugin.php Event::listen('backend.filter.extendScopes', function ($widget) { // Only for the Posts controller if (( ! $widget->getController() instanceof \Rainlab\Blog\Controllers\Posts)) { return; } $widget->addScopes([ 'Trashed' => [ 'label' => 'Hide trashed', 'type' => 'checkbox', 'scope' => 'trashed' ], ]); });
Вы можете прочитать больше о фильтрах списка в документации . Приведенный выше код довольно прост и содержит только несколько параметров. Однако атрибут scope
должен быть именем метода области запроса, определенного в связанном экземпляре модели ( Models\Post
).
Расширяемые классы
Черта October\Rain\Extension\ExtendableTrait
предоставляет волшебный способ динамически расширять существующий класс, добавляя новые методы, свойства, поведение и т. Д. В нашем примере нам нужно добавить новый метод в модель posts для обработки нашего фильтра области видимости.
// plugin.php \Rainlab\Blog\Models\Post::extend(function ($model) { $model->addDynamicMethod('scopeTrashed', function ($query) { return $query->where('deleted_at', '=', null); }); });
Мы можем сделать то же самое с addDynamicProperty
, asExtension
и т. Д. Давайте asExtension
наш список сообщений, чтобы увидеть, работают ли наши изменения.
Конечно, у нас пока нет сообщений с мусором, потому что мы должны закончить последнюю часть: перехватить удаление сообщения и только обновить столбец deleted_at
.
Совет: вместо использования атрибута scope
вы можете использовать conditions
чтобы указать простое условие where. Код ниже дает тот же результат, что и при использовании областей действия модели.
$widget->addScopes([ 'Trashed' => [ 'label' => 'Hide trashed', 'type' => 'checkbox', 'conditions' => 'deleted_at IS NULL', ], ]);
Красноречивые события
Eloquent запускает список событий для каждого действия (создание, обновление, удаление и т. Д.). В этом случае нам нужно подключиться к событию delete и предотвратить удаление записи.
При удалении записи событие deleting
вызывается перед выполнением фактического действия по удалению, а deleted
событие запускается впоследствии. Если вы вернете false
в событии deleting
, действие будет прервано.
// plugin.php Event::listen('eloquent.deleting: RainLab\Blog\Models\Post', function ($record) { $record->deleted_at = Carbon::now(); $record->save(); return false; });
Теперь мы готовы проверить окончательный результат! Затем удалите некоторые записи, а затем перейдите на страницу списка публикаций, чтобы узнать, можно ли переключать элементы в списке.
Вывод
Эта статья была кратким обзором того, как можно расширить различные части платформы OctoberCMS. Вы можете прочитать больше об этом в разделе расширенных плагинов документации. Если у вас есть какие-либо вопросы или комментарии, обязательно разместите их ниже!