Статьи

Расширение OctoberCMS — Создание плагина Soft-Delete

Разработчики обычно придерживаются новой CMS из-за ее простоты и расширяемости. OctoberCMS представляет собой возвращение к основам CMS и предоставляет приятный опыт как для разработчиков, так и для пользователей. В этой статье я собираюсь продемонстрировать некоторые аспекты CMS, которые делают его расширяемым, и мы также попробуем простой плагин для расширения функциональности другого плагина.

OctoberCMS LOGO

Вступление

Каждая 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. Вы можете прочитать больше об этом в разделе расширенных плагинов документации. Если у вас есть какие-либо вопросы или комментарии, обязательно разместите их ниже!