首页 > 解决方案 > Laravel 删除记录会影响新记录的排序

问题描述

我成功地可以删除一张票,并且该记录已从数据库中删除。如果我有两张票“票 1 和票 2”,我可以很高兴地删除票 1,因为它是第一张票,并且可以删除票 2,因为它是票 1 之后的下一张票(以任何顺序!)

但是,我有一个有趣的老问题,如果我不按降序连续删除票

以这些票为例:

工单 1 - 10:00 创建的时间 工单 2 - 10:15 创建的时间 工单 3 - 10:30 创建的时间

因此,如果我删除票证 3(因为那是最后创建的票证),删除票证 2,删除票证 1,而是删除中间票证“票证 2”,我在尝试创建另一个票证时收到错误消息。新工单已创建,但“作者”和“组织”字段未填充,当我打开工单时,我收到“无消息错误”——因为工单未能完全创建。

当使用空的 'author' 和 'organisation' 字段以及 'no message' laravel 错误创建此新工单时,ID 会在最初低于它的 ID 之上添加一个。因此,例如,如果我删除 id 为 2 的票 2(只留下 id 为 1 和 3 的票),当我创建另一个票时,它会收到一个正确的 ID 4,但在 phpMyAdmin 中显示的是 4当然,在 3 之上而不是在 3 之后。ID 为“3”的票证的“slug”属性也会增加到“ticket-title-2”,这也不应该发生。但是,我认为这与 slug 增量无关,因为没有方法(如图所示在票证模型中)问题仍然存在。

我还认为这与我使用的删除方法有关,因此尝试使用 $ticket->forceDelete() 而不是 $ticket->delete(),但这似乎不起作用。我尝试过我的创建方法,但经过数小时的调试后,我仍然在努力找出这个问题出在哪里。但是我知道问题与删除票证时的订购有关,但是我不知道在哪里触发了这个问题。

路线

Route::delete('ticket/{ticket}', 'AdminController@delete')->name('admin.delete');

票务-商店功能

public function store()
    {
        if (Auth::user()->organisation == "Bournemouth University") {
            $ticketCode = "BU";
        } else {
            $ticketCode = "NHS";
        }

        $attributes = request()->validate([
            'title' => ['required', 'min: 2'],
            'description' => ['required'],
            'subject_area' => ['required']
        ]);

        Ticket::create($attributes);
        $slug = str_slug(Ticket::get()->last()->title, '-');

        Ticket::get()->last()->update(['code' => $ticketCode, 'user_id' => Auth::user()->id, 'slug' => $slug, 'author' => Auth::user()->username]);

        $slug = Ticket::get()->last()->slug;

        return redirect()->route('ticket.show', $slug);
    }

管理员控制器 - 删除方法

public function delete(Ticket $ticket){
        $ticket->delete();
        return redirect('/');
    }

票务页面 - 删除表格

<div class="modal fade" id="delete" tabindex="-1" role="dialog">
                            <div class="modal-dialog" role="document">
                                <div class="modal-content">
                                    <div class="modal-header">
                                        <h4>Are you sure you want to delete this post?</h4>
                                    </div>
                                    <div class="modal-body">
                                        <form id="delete-post" method="POST" action="{{route('admin.delete', $slug->slug) }}">
                                            @csrf
                                            @method('DELETE')
                                            <div style="text-align: center">
                                                <button type="submit" class="btn btn-success"
                                                        id="confirm-del" data-dismiss="modal"
                                                        style="font-weight: bold;">Yes
                                                </button>
                                                <button type="button" class="btn btn-danger" data-dismiss="modal"
                                                        style="font-weight: bold;">No
                                                </button>
                                            </div>
                                        </form>
                                        <script type="text/javascript">
                                            $(function(){
                                                $('#confirm-del').on('click', function(){
                                                    $('#delete-post').submit();
                                                });
                                            });
                                        </script>
                                    </div>
                                </div>
                            </div>
                        </div>

工单模型 - slug 增量方法

 public function setSlugAttribute($value){
        if(static::whereSlug($slug = str_slug($value))->exists()){
            $slug = $this->incrementSlug($slug);
        }

        $this->attributes['slug'] = $slug;
    }

    public function incrementSlug($slug){
        $firstSlug = $slug;
        $count = 2;

        while(static::whereSlug($slug)->exists()){
            $slug = "{$firstSlug}-" . $count++;
        }
        return $slug;
    }

抱歉,如果我不清楚。我希望有人能指出我可能出错的地方或如何纠正这个问题的正确方向。

标签: laraveleloquentrecord

解决方案


我不知道它是否解决了你的问题,但每次你写

Ticket::get()->last()

您正在进行大型数据库查询。事实上,这翻译为“给我所有的结果,在你得到的结果中,给我最后一个”。如果您想获得最新的(通过 created_at 订单),您可以使用:

Ticket::latest()->first()

但是,每次调用它时,这也是一个查询。

出于多种原因(包括并发性、速度、可维护性),我建议一次性完成:

public function store()
{
    if (Auth::user()->organisation == "Bournemouth University") {
        $ticketCode = "BU";
    } else {
        $ticketCode = "NHS";
    }

    $attributes = request()->validate([
        'title' => ['required', 'min: 2'],
        'description' => ['required'],
        'subject_area' => ['required']
    ]);

    // Now, populate the attributes before creating the ticket.
    $attributes['slug'] = str_slug(Ticket::get()->last()->title, '-');
    $attributes['code'] = $ticketCode;
    $attributes['user_id'] = Auth::user()->id;
    $attributes['author'] = Auth::user()->username;

    $ticket = Ticket::create($attributes);

    // And we get the slug directly from the ticket
    return redirect()->route('ticket.show', $ticket->slug);
}

PS:对这段代码的更多改进可能是:

  • 使用事件来设置 slug,而不是 mutators。
  • 使用用户和工单之间的关系并删除用户名字段。

推荐阅读