与Laravel中软删除相关的问题

3

我有一些关于Laravel中软删除的问题。我已经搜索了它的含义和作用,关于软删除最容易理解的部分是这句话:

"当模型被软删除时,它们并没有从你的数据库中实际移除。相反,一个 deleted_at 属性会被设置在模型上并插入到数据库中。如果一个模型有一个非空的 deleted_at 值,那么这个模型就被软删除了。要为一个模型启用软删除,请在模型上使用 Illuminate\Database\Eloquent\SoftDeletes Trait,并将 deleted_at 列添加到你的 $dates 属性中:"

所以根据这句话,这里是我的问题:

Q1:

当我在代码中使用软删除,尝试删除某些数据时,视图页面(blade.php)中的数据是否会消失,而数据库中仍然包含这些数据?

Q2:

我看到有人使用了 static::deleting,我不太明白它是如何工作的?你能解释一下它的作用吗?谢谢

Q3:

如何使用软删除删除数据?我看到有人只是在模型中放置一些内容,而不是使用按钮,那么这是否意味着只能在模型内手动删除它,而不能在视图页面中点击删除按钮?

5个回答

5

问题1

默认情况下:是的。
这取决于您的查询。使用软删除时,默认情况下,Laravel将查询所有软删除的模型。当您还想获取软删除的模型时,需要在查询中调用withTrashed()方法。在此处阅读更多信息:
https://laravel.com/docs/5.5/eloquent#querying-soft-deleted-models

要理解withTrashed()的作用,您需要了解软删除的工作原理。通过向数据库表添加名为deleted_at新列来软删除模型。它的值默认为null。当您软删除模型时,Laravel会将当前时间戳放入该列中。因此,此字段不再包含null值。

在使用软删除时查询模型时,Laravel将一个deleted_at is null条件追加到查询中。调用withTrashed()方法将从查询中删除该条件。

请查看默认查询修改器withTrashed方法的源代码。


问题2

那些是事件。您可以调用它来告诉Laravel,当发生此事件时,应执行该特定闭包。在您的示例中,正在侦听“deleting”事件。在此处查看更多信息:
https://laravel.com/docs/5.5/eloquent#events


问题3

您可以使用forceDelete()方法完全删除可软删除的模型。请参阅“永久删除模型”:
https://laravel.com/docs/5.5/eloquent#querying-soft-deleted-models


只针对您想软删除的模型表。例如,如果您有“Post”和“Comment”,并且评论可以软删除,则只需将该列添加到“comments”表中即可。 - tinyoverflow
不会出现这样的错误,因为在软删除时,原始数据仍然存在于其位置。当您最终删除数据时可能会出现错误,但这取决于您的数据库设置,与软删除无关。 - tinyoverflow
啊,我明白了,非常感谢你帮助我理解。还有一件事,你有没有任何教程视频或网站,可以逐步演示如何进行软删除?你在问题中提供的链接我已经阅读过了,但我觉得它们提供的信息太少了。 - blastme
哈哈哈,因为在YouTube上没有太多关于它的视频,所以我在这里发布了。无论如何,非常感谢您的帮助。 - blastme
非常感谢,稍后会观看 :) - blastme
显示剩余4条评论

3

问题1:当我在代码中使用软删除时,如果我试图删除一些数据,那么视图页面(blade.php)中的数据是否会消失,而数据库仍然包含这些数据?

是的。软删除会在数据库中填充deleted_at列。从此以后,Eloquent将不会检索这些数据(除非您要求)。如果您使用自定义SQL请求,则需要添加WHERE deleted_at IS NULL

问题2:我看到一些人使用static::deleting这个东西,我真的不太明白它是如何工作的?你能解释一下它是做什么的吗?谢谢。

我平常不怎么用它,但它是一个可以调用的事件(见这里),可以自动删除相关内容(例如,如果您删除一个用户,也可以删除他所有的帖子。它类似于级联删除)

问题3:如何使用软删除删除数据?我看到有人只是将一些东西放入他们的模型中,而不是使用按钮,那么这是否意味着您只能手动在模型内部进行删除,而不能直接点击视图页面上的删除按钮呢?

要使用软删除,您只需要$object->destroy($id)$myEloquentRequest->where(...)->delete()。 如果您想强制进行真正的删除(因此条目将从数据库中被彻底删除),您可以使用$flight->forceDelete(); 有关更多信息,请参见这里。 您可以在任何地方进行删除。单击按钮将用户带到您控制器中的delete()方法。您可以在那里删除或调用模型内部的方法来触发删除(以及可能一些更复杂的删除操作,如事件...)


对于 deleted_at 列,我需要将其添加到数据库表中吗?还是它会自动为我完成?或者只需将其放在我的模型中(我看到有些人将其放在受保护的某个位置)? - blastme
你需要添加它。如果你使用迁移,你只需添加 $table->softdeletes() - JérémyCasper
抱歉,我现在有点困惑,我以为应该将 deleted_at 列放在里面?为什么要使用软删除? - blastme
在您的数据库表中,您需要像updated_at或created_at列一样拥有一个名为“deleted_at”的列(如果您使用这些列)。如果您在Laravel中使用迁移文件,您可以使用上面的行自动创建此列。 - JérémyCasper
哦,好的,我想我明白你的意思了。一旦你添加了 $table->softdeletes(),deleted_at 列就会出现吗? - blastme
你需要在控制台中运行迁移命令(php artisan migrate),然后就可以了。但是请注意,如果你的表已经存在,你需要创建一个新的迁移文件来修改表结构(或者运行php artisan migrate:refresh,但这会删除你当前的数据)。 - JérémyCasper

2

澄清一下你的观点。 1. 当我们在代码中使用软删除时,删除时间戳将从null更新为当前时间戳,因此在从项目中的任何地方查询该特定表格的数据时,Eloquent模型将自动返回已删除时间戳设置为NULL的数据,即它不是软删除。

  1. people using something called static::deleting. you might have seen somewhat like this example if I am understanding your question in right way:

    class X-Model extends Eloquent {

    public function xy()
    {
        return $this->has_many('XY_Model');
    }
    
    // this is a recommended way to declare event handlers
    protected static function boot() {
        parent::boot();
    
        static::deleting(function($x) { 
         // before delete() method call this
             $user->xy()->delete();
             // do the rest of the cleanup...
        });
    }
    

    } This is a use-case for Eloquent events to delete a record which will use the "deleting" event to do the cleanup.

  2. delete data using soft delete

现在,在调用此函数后,您可以从表中软删除数据,如果在模型中正确维护了关系,则还可以从其他相关表中软删除数据。这实际上被称为级联效应。以下是一个示例,以便您更好地了解。

模型结构:

namespace App\Models;

use Illuminate\Database\Eloquent\Model;
use App\Utilities\Uuids;
use Illuminate\Database\Eloquent\SoftDeletes;
use Iatstuti\Database\Support\CascadeSoftDeletes;

class XFolder extends Model
{
    use SoftDeletes, CascadeSoftDeletes;
    use Uuids;
    protected $connection = 'XDB';
    protected $table = 'x_folder';
    protected $dates = ['deleted_at'];
    public $incrementing = false;
    protected $cascadeDeletes = ['XReference']; //related table with foreign keys
    protected $visible = [ 'id', 'x_id', 'xz_id', 'at_id', 'title', 'description', 'description', 'status', 'created_on' , 'is_active'];

    protected $fillable = [
     'x_id',
     'xz_id',
     'at_id',
     'title',
     'description',
     'status',
     'created_on',
     'is_active'
    ];

    public function XReference()
    {
        return $this->hasMany('App\Models\XReference', 'x_id');
    }
}

现在你可以在控制器中这样调用:

public function deleteData($id)
    {
        $results = $this->getModel()->where('id', $id)->deleteData();
        return $results;
    }

这将会删除数据(以级联方式进行软删除)。


2

软删除指的是不在数据库中删除记录。因此,我们处理一个标志来管理记录是否已被删除。

让我用例子进一步解释:

在我们的记录中有很多用户,因此我们在数据库中添加了一个字段delete_at,并将其默认值设置为null,这样它的记录就没有被删除。

现在当我们获取所有用户数据时,我们编写查询语句如下:

Select * from user where delete_at = null

所以这个查询会返回所有未被删除的用户数据。

现在我们要删除这个用户,当我们点击删除按钮时,我们会创建一个自定义查询并将该用户的delete_at字段更新为当前日期时间。

Update delete_at=date() where user_id = 1

现在这个记录是软删除的。

现在我回答你的问题:

问1)软删除后没有数据显示,因为当我们获取数据时,会检查delete_at字段是否为空。


哦,我明白了。那么有什么方法可以点击“删除”按钮,只让与该数据相关的视图消失,但数据库数据仍然存在吗? - blastme
如果您使用软删除,它只会更新delete_at字段的值,但您的数据库数据保持不变。 - bipin patel
如果您喜欢我的答案,可以接受这个答案,这将有助于其他人更好地理解。 - bipin patel

1

Q1:当我在代码中使用软删除时,当我尝试删除一些数据时,视图页面(blade.php)中的数据是否会消失,而数据库仍然包含这些数据?

是的,如果您的模型使用softDelete,那么搜索查询将如下所示:Select * from table_name where delete_at = null

Q2:我看到有些人使用称为static::deleting的东西,我不太明白它是如何工作的?你能解释一下它是做什么的吗?

你可以使用Modelname::destroy($id)静态方法进行操作。

它会销毁设置了$id的模型对象。通过销毁,我指的是:它会更新deleted_at列,因此应用程序将其视为已软删除的对象。

Q3:如何使用软删除删除数据?我看到有些人只是将一些内容放入模型中,而不是使用按钮,那么这是否意味着您只能手动在模型内部删除它,而不能只需在视图页面上单击删除按钮?

以下是我的一个项目示例:

我在合作伙伴屏幕上有一个删除按钮,它的路由为partner/{{ id }}/delete

路由如下:Route::get('/partner/{id}/delete', 'PartnerController@deletePartner');

这个操作执行什么:

public function deletePartner($partnerId = 0){

    if ($partnerId > 0){
        Partner::destroy($partnerId);
    }

    return redirect("/partner");
}

如果我点击删除按钮,它会检查ID是否设置,然后“销毁”它(软删除)。删除后,它会重定向回合作伙伴页面。
编辑:
对于问题3中给出的示例,当您删除数据时,数据库数据是否会消失还是只有视图?
它只会从视图中消失。在数据库中,它将被存储为:
id name ... created_at       updated_at       deleted_at
1  foo  ... 2017-10-01 00:00 2017-10-01 00:00 NULL
2  bar  ... 2017-10-01 00:00 2017-10-01 00:00 2017-10-25 16:00

第一个是未删除的对象,第二个是软删除的对象,只有第一个会显示在视图中。

对于问题3中给出的示例,当您删除数据时,数据库数据会消失还是只有视图消失? - blastme
好的,我只是想问一下,你知道有没有任何教程视频或网站可以逐步演示如何进行软删除吗? - blastme
你可以从文档中学到很多东西。这里是软删除的部分。此外,你也可以在Laracast上学到很多东西。他们有很多视频教程。这个是关于软删除的内容。 - Feralheart
哈哈哈,我已经阅读了文档,但无论如何还是非常感谢你的帮助 :) - blastme

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接