Laravel 删除记录会影响新记录的排序
Laravel deleting a record affects the ordering of new records
我可以成功删除工单,并且记录已从数据库中删除。如果我有两张票 "Ticket 1 and Ticket 2",我可以愉快地删除票 1,因为它是第一张票,并且可以删除票 2,因为它是票 1 之后的下一张票(顺序不限!)
但是,我有一个有趣的老问题,如果我不按连续降序删除门票
以这些票为例:
工单 1 - 创建时间 10:00
工单 2 - 创建时间 10:15
工单 3 - 创建于 10:30
的时间
所以,如果我删除工单 3(因为那是最后创建的工单),删除工单 2,删除工单 1 并删除中间的工单 'Ticket 2'我在尝试创建另一个工单时收到错误消息.新工单已创建,但 'author' 和 'organisation' 字段未填充,当我打开工单时,我得到 'No message error' -- 因为工单未能完全创建。
当使用空 '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;
}
如果我不太清楚,请见谅。我希望有人能指出我可能出错的正确方向或如何纠正这个问题。
不知道能不能解决你的问题,不过每次都写
Ticket::get()->last()
您正在进行大型数据库查询。实际上,这翻译为 "get me all the results, and in the results you got, get me the last one"。如果你想获得最新的(按 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,而不是 mutator。
- 使用用户和工单之间的关系并删除用户名字段。
我可以成功删除工单,并且记录已从数据库中删除。如果我有两张票 "Ticket 1 and Ticket 2",我可以愉快地删除票 1,因为它是第一张票,并且可以删除票 2,因为它是票 1 之后的下一张票(顺序不限!)
但是,我有一个有趣的老问题,如果我不按连续降序删除门票
以这些票为例:
工单 1 - 创建时间 10:00 工单 2 - 创建时间 10:15 工单 3 - 创建于 10:30
的时间所以,如果我删除工单 3(因为那是最后创建的工单),删除工单 2,删除工单 1 并删除中间的工单 'Ticket 2'我在尝试创建另一个工单时收到错误消息.新工单已创建,但 'author' 和 'organisation' 字段未填充,当我打开工单时,我得到 'No message error' -- 因为工单未能完全创建。
当使用空 '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;
}
如果我不太清楚,请见谅。我希望有人能指出我可能出错的正确方向或如何纠正这个问题。
不知道能不能解决你的问题,不过每次都写
Ticket::get()->last()
您正在进行大型数据库查询。实际上,这翻译为 "get me all the results, and in the results you got, get me the last one"。如果你想获得最新的(按 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,而不是 mutator。
- 使用用户和工单之间的关系并删除用户名字段。