You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

软删除嵌套子项:关于Model_Announcement与评论模型关联的技术咨询

Implementing Soft Delete for Nested Announcement Comments

Great question! Combining nested set behavior with soft delete requires a few targeted adjustments to your models and database, since your Model_Announcement_Comment inherits from Model_Nestedset (for tree structure) but needs the soft delete functionality normally provided by Model_Soft. Here's a step-by-step solution tailored to your setup:


1. Add the Soft Delete Column to Your Comments Table

First, you need a deleted_at timestamp column in your announcement_comments table to track when a comment is soft deleted. Create a migration to add this column:

class Migration_Add_deleted_at_to_announcement_comments extends \Fuel\Core\Migration
{
    public function up()
    {
        \DBUtil::add_fields('announcement_comments', array(
            'deleted_at' => array('type' => 'timestamp', 'null' => true),
        ));
    }

    public function down()
    {
        \DBUtil::drop_fields('announcement_comments', array('deleted_at'));
    }
}

Run the migration to apply the change to your database.


2. Modify Model_Announcement_Comment to Include Soft Delete Logic

Since you can't inherit from both Model_Nestedset and Model_Soft directly, we'll add soft delete functionality manually to your comment model. This includes default scopes to exclude deleted items, overriding the delete method to soft delete instead of hard delete, and optional restore functionality.

class Model_Announcement_Comment extends Model_Nestedset
{
    // Enable soft delete functionality
    protected static $_soft_delete = true;

    protected static $_belongs_to = array(
        'announcement' => array(
            'key_from' => 'announcement_id',
            'model_to' => 'Model_Announcement',
            'key_to' => 'id',
        ),
    );

    // Define scopes to handle deleted items
    protected static $_scopes = array(
        // Default scope: exclude deleted comments
        'not_deleted' => array(
            'where' => array(
                array('deleted_at', '=', null),
            ),
        ),
        // Scope to include deleted comments when needed
        'with_deleted' => array(
            'scope' => function($query) {
                $query->where_open()
                      ->where('deleted_at', '=', null)
                      ->or_where('deleted_at', 'is not', null)
                      ->where_close();
            },
        ),
    );

    // Apply the default not_deleted scope on model initialization
    public static function _init()
    {
        static::add_scope('not_deleted');
    }

    // Override delete method to perform soft delete
    public function delete($cascade = null)
    {
        if (static::$_soft_delete === true) {
            // Set the deleted_at timestamp
            $this->deleted_at = \Date::time()->format('mysql');
            $this->save($cascade);

            // Optional: Cascade soft delete to all child comments
            $children = $this->children()->get();
            foreach ($children as $child) {
                $child->delete($cascade);
            }

            return true;
        } else {
            // Fallback to hard delete if soft delete is disabled
            return parent::delete($cascade);
        }
    }

    // Optional: Method to restore a soft deleted comment (and its children)
    public function restore()
    {
        if ($this->deleted_at !== null) {
            $this->deleted_at = null;
            $this->save();

            // Restore child comments too
            $children = $this->children()->with_deleted()->get();
            foreach ($children as $child) {
                $child->restore();
            }

            return true;
        }
        return false;
    }
}

3. Adjust Model_Announcement for Cascade Soft Delete

Your announcement model has cascade_delete set to true, which by default would trigger a hard delete on comments. To make this cascade soft delete instead, override the delete method in Model_Announcement:

class Model_Announcement extends Model_Soft
{
    protected static $_has_many = array(
        'comments' => array(
            'key_from' => 'id',
            'model_to' => 'Model_Announcement_Comment',
            'key_to' => 'announcement_id',
            'cascade_save' => true,
            'cascade_delete' => false, // Disable default hard delete cascade
        ),
    );

    public function delete($cascade = null)
    {
        if (static::$_soft_delete === true) {
            // Soft delete all associated comments first
            foreach ($this->comments as $comment) {
                $comment->delete();
            }
            // Then soft delete the announcement itself
            $this->deleted_at = \Date::time()->format('mysql');
            return $this->save();
        } else {
            return parent::delete($cascade);
        }
    }
}

Key Notes

  • Default Behavior: By default, all queries for comments will exclude soft deleted items (thanks to the not_deleted scope). To include deleted comments, use Model_Announcement_Comment::with_deleted()->find().
  • Nested Set Integrity: Soft deleted comments remain in the database with their lft/rgt values intact, but they're ignored by default queries. This keeps your nested tree structure valid for active comments.
  • Cascade Control: The optional child cascade in the comment delete method ensures that deleting a parent comment soft deletes all its replies. You can remove this if you want to keep child comments active even when their parent is deleted.

内容的提问来源于stack exchange,提问作者Xaris Rg

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.25 06:21:52