OctoberCMS:插件扩展性深度探索及软删除插件实战
开发者通常青睐易用且可扩展的CMS。OctoberCMS 秉持简洁至上的理念,为开发者和用户带来愉悦的体验。本文将演示OctoberCMS 的一些可扩展特性,并通过一个简单的插件扩展另一个插件的功能。
deleted_at
字段。此字段将保存文章删除的时间戳。然后,插件扩展文章列表以包含此新字段作为列,并添加一个过滤器来显示或隐藏已删除的文章。deleted_at
列。这是通过挂接到 Eloquent 触发的 deleting
事件来实现的,阻止记录的删除。取而代之的是,deleted_at
字段将更新为当前时间戳,并保存记录。每个CMS都有一个插件系统来扩展平台的功能,我们通过可以深入CMS内部机制的程度来衡量其扩展性。然而,我们这里讨论的不仅仅是CMS本身,也包括插件!
如果您构建一个插件,您需要确保其他开发者可以修改您的部分功能。例如,我们有一个博客插件,用户可以通过选择列表中的文章来发布文章。最好触发一个事件来表明已发布新文章,另一个开发者可以挂接到此事件,并通过电子邮件通知订阅的用户!
<code class="language-php">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(); } }</code>
其他开发者可以监听此事件来处理已发布的文章。
<code class="language-php">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('us@example.com', 'New post by ' . $user->name); $message->to($user->email); }); }); });</code>
我们将主要使用事件来挂接到请求周期的不同部分。让我们从一个具体的例子开始,以便更好地理解。
如果您使用过OctoberCMS一段时间,您一定知道Rainlab Blog插件。它允许您在后端添加文章并将其附加到类别,并且您可以使用组件在前端显示它们。
在文章列表页面,我们可以删除文章。但是,如果我们想软删除它们呢?让我们看看我们能否做到这一点,并了解更多关于OctoberCMS扩展性的知识。
使用脚手架助手命令创建一个新的插件用于我们的演示,并在Plugin.php文件中更新插件详细信息。
<code class="language-php">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(); } }</code>
谈到软删除时,首先想到的是数据库中需要存在的 deleted_at
字段列。
在 blogplus/updates
文件夹下创建一个名为 create_posts_deleted_at_field.php
的新文件,并更新 version.yaml
文件。
<code class="language-php">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('us@example.com', 'New post by ' . $user->name); $message->to($user->email); }); }); });</code>
<code class="language-bash">php artisan create:plugin rafie.blogplus</code>
迁移类将更改 rainlab_blog_posts
表并添加我们的 deleted_at
列,其默认值为 null。不要忘记运行 php artisan plugin:refresh rafie.blogplus
命令才能使更改生效。
接下来,我们必须将我们的字段作为列添加到列表中以进行显示。OctoberCMS 为我们提供了一个事件来挂接,并更改当前显示的小部件(后端列表被认为是小部件)。
<code class="language-yaml"># updates/version.yaml 1.0.1: - First version of blogplus. - create_posts_deleted_at_field.php</code>
注意:以上代码应放在 Plugin@boot
方法中。
我们有一个 if 语句来防止我们的代码在每个页面上执行,然后我们将一个新列添加到列表小部件中,我们还可以使用 removeColumn
方法删除任何现有的列。查看文档以了解可用的列选项列表。
文章列表顶部的栏允许用户使用日期、类别等过滤列表。在我们的例子中,我们需要一个过滤器来显示/隐藏已删除的文章。
<code class="language-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'); }); } }</code>
您可以在文档中阅读更多关于列表过滤器的信息。上面的代码相当简单,只包含几个选项。但是,scope
属性应该是 Models\Post
模型实例中定义的查询范围方法的名称。
OctoberRainExtensionExtendableTrait trait 提供了一种神奇的方法来动态扩展现有类,方法是添加新的方法、属性、行为等。在我们的示例中,我们需要向文章模型添加一个新方法来处理我们的范围过滤器。
<code class="language-php">// 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', ], ]); });</code>
我们可以对 addDynamicProperty
、asExtension
等做同样的事情。让我们刷新我们的文章列表,看看我们的更改是否有效。
当然,我们还没有任何已删除的文章,因为我们需要完成最后一部分:拦截文章的删除操作,只更新 deleted_at
列。
提示:与其使用 scope
属性,您可以使用条件来指定一个简单的 where 条件。下面的代码与使用模型范围的效果相同。
<code class="language-php">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(); } }</code>
Eloquent 在每个操作(创建、更新、删除等)上都会触发一系列事件。在这种情况下,我们需要挂接到删除事件并阻止记录的删除。
删除记录时,在执行实际删除操作之前会触发 deleting
事件,之后会触发 deleted
事件。如果您在 deleting
事件中返回 false,则操作将中止。
<code class="language-php">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('us@example.com', 'New post by ' . $user->name); $message->to($user->email); }); }); });</code>
现在我们准备测试最终结果!继续删除一些记录,然后转到文章列表页面,看看是否可以切换列表中的已删除项目。
本文快速概述了如何扩展 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
方法为某些记录禁用软删除功能。这允许您从软删除功能中排除某些记录。
以上是延长10月CMS-构建软耗尽插件的详细内容。更多信息请关注PHP中文网其他相关文章!