OctoberCMS:插件扩展性深度探索及软删除插件实战
开发者通常青睐易用且可扩展的CMS。OctoberCMS 秉持简洁至上的理念,为开发者和用户带来愉悦的体验。本文将演示OctoberCMS 的一些可扩展特性,并通过一个简单的插件扩展另一个插件的功能。
deleted_at
字段。此字段将保存文章删除的时间戳。然后,插件扩展文章列表以包含此新字段作为列,并添加一个过滤器来显示或隐藏已删除的文章。deleted_at
列。这是通过挂接到 Eloquent 触发的 deleting
事件来实现的,阻止记录的删除。取而代之的是,deleted_at
字段将更新为当前时间戳,并保存记录。每个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);
});
});
});
我们将主要使用事件来挂接到请求周期的不同部分。让我们从一个具体的例子开始,以便更好地理解。
如果您使用过OctoberCMS一段时间,您一定知道Rainlab Blog插件。它允许您在后端添加文章并将其附加到类别,并且您可以使用组件在前端显示它们。
在文章列表页面,我们可以删除文章。但是,如果我们想软删除它们呢?让我们看看我们能否做到这一点,并了解更多关于OctoberCMS扩展性的知识。
使用脚手架助手命令创建一个新的插件用于我们的演示,并在Plugin.php文件中更新插件详细信息。
php artisan create:plugin rafie.blogplus
谈到软删除时,首先想到的是数据库中需要存在的 deleted_at
字段列。
在 blogplus/updates
文件夹下创建一个名为 create_posts_deleted_at_field.php
的新文件,并更新 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
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreatePostsDeletedAtField extends Migration
{
public function up()
{
Schema::table('rainlab_blog_posts', function (Blueprint $table) {
$table->timestamp('deleted_at')->nullable()->default(null);
});
}
public function down()
{
Schema::table('rainlab_blog_posts', function (Blueprint $table) {
$table->dropColumn('deleted_at');
});
}
}
迁移类将更改 rainlab_blog_posts
表并添加我们的 deleted_at
列,其默认值为 null。不要忘记运行 php artisan plugin:refresh rafie.blogplus
命令才能使更改生效。
接下来,我们必须将我们的字段作为列添加到列表中以进行显示。OctoberCMS 为我们提供了一个事件来挂接,并更改当前显示的小部件(后端列表被认为是小部件)。
// plugin.php 在Plugin类的boot方法中
Event::listen('backend.list.extendColumns', function ($widget) {
if (!($widget->getController() instanceof \Rainlab\Blog\Controllers\Posts)) {
return;
}
$widget->addColumns([
'deleted_at' => [
'label' => 'Deleted',
'type' => 'date',
],
]);
});
注意:以上代码应放在 Plugin@boot
方法中。
我们有一个 if 语句来防止我们的代码在每个页面上执行,然后我们将一个新列添加到列表小部件中,我们还可以使用 removeColumn
方法删除任何现有的列。查看文档以了解可用的列选项列表。
文章列表顶部的栏允许用户使用日期、类别等过滤列表。在我们的例子中,我们需要一个过滤器来显示/隐藏已删除的文章。
// plugin.php 在Plugin类的boot方法中
Event::listen('backend.filter.extendScopes', function ($widget) {
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 trait 提供了一种神奇的方法来动态扩展现有类,方法是添加新的方法、属性、行为等。在我们的示例中,我们需要向文章模型添加一个新方法来处理我们的范围过滤器。
// plugin.php 在Plugin类的boot方法中
\Rainlab\Blog\Models\Post::extend(function ($model) {
$model->addDynamicMethod('scopeTrashed', function ($query) {
return $query->whereNull('deleted_at');
});
});
我们可以对 addDynamicProperty
、asExtension
等做同样的事情。让我们刷新我们的文章列表,看看我们的更改是否有效。
当然,我们还没有任何已删除的文章,因为我们需要完成最后一部分:拦截文章的删除操作,只更新 deleted_at
列。
提示:与其使用 scope
属性,您可以使用条件来指定一个简单的 where 条件。下面的代码与使用模型范围的效果相同。
$widget->addScopes([
'Trashed' => [
'label' => 'Hide trashed',
'type' => 'checkbox',
'conditions' => 'deleted_at IS NULL',
],
]);
Eloquent 在每个操作(创建、更新、删除等)上都会触发一系列事件。在这种情况下,我们需要挂接到删除事件并阻止记录的删除。
删除记录时,在执行实际删除操作之前会触发 deleting
事件,之后会触发 deleted
事件。如果您在 deleting
事件中返回 false,则操作将中止。
// plugin.php 在Plugin类的boot方法中
use Carbon\Carbon;
Event::listen('eloquent.deleting: RainLab\Blog\Models\Post', function ($record) {
$record->deleted_at = Carbon::now();
$record->save();
return false;
});
现在我们准备测试最终结果!继续删除一些记录,然后转到文章列表页面,看看是否可以切换列表中的已删除项目。
本文快速概述了如何扩展 OctoberCMS 平台的不同部分。您可以在文档的扩展插件部分阅读更多相关信息。如果您有任何问题或意见,请在下方留言!
OctoberCMS 中的软删除插件旨在防止永久性数据丢失。当您删除记录时,它不会从数据库中完全删除。相反,会为该记录设置一个 deleted_at
时间戳。这意味着从应用程序的角度来看,该记录被认为是“已删除”的,但如果需要,仍然可以检索到它。这在可能意外删除数据的场景中特别有用,因为它允许轻松恢复。
硬删除会永久地从数据库中删除记录,除非您有备份,否则无法恢复。另一方面,软删除只是将记录标记为已删除,而不会实际将其从数据库中删除。这允许您在需要时恢复记录。
要在 OctoberCMS 中实现软删除功能,您需要创建一个插件。这包括创建一个新插件,向数据库表添加 deleted_at
列,并更新您的模型以使用 SoftDeletes
trait。然后,您可以使用模型上的 delete
方法来软删除记录,并使用 restore
方法来恢复它。
您可以通过创建单元测试来测试软删除功能。这包括创建一个新的测试用例,在数据库中创建一个新记录,软删除它,然后断言它仍然存在于数据库中,但被标记为已删除。
是的,您可以将软删除功能与现有记录一起使用。您只需要向现有的数据库表添加 deleted_at
列。所有现有记录的此列都将具有 null
值,表示它们尚未被删除。
要恢复软删除的记录,您可以使用模型上的 restore
方法。这将从记录中删除 deleted_at
时间戳,有效地“取消删除”它。
是的,您可以使用模型上的 forceDelete
方法永久删除软删除的记录。这将像硬删除一样从数据库中删除记录。
要查看所有记录,包括软删除的记录,您可以使用模型上的 withTrashed
方法。这将返回所有记录,无论它们是否已被软删除。
deleted_at
列的名称吗?是的,您可以通过覆盖模型中的 getDeletedAtColumn
方法来自定义 deleted_at
列的名称。如果 deleted_at
不适合您的需求,这允许您使用不同的列名。
是的,您可以使用模型上的 withoutGlobalScope
方法为某些记录禁用软删除功能。这允许您从软删除功能中排除某些记录。
Disclaimer: All resources provided are partly from the Internet. If there is any infringement of your copyright or other rights and interests, please explain the detailed reasons and provide proof of copyright or rights and interests and then send it to the email: [email protected] We will handle it for you as soon as possible.
Copyright© 2022 湘ICP备2022001581号-3