php 如何使用 Laravel Eloquent 删除多条记录
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/35046082/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to delete multiple records using Laravel Eloquent
提问by Code Poet
Now this, from what I can see, should have been simple.
现在,从我所见,这应该很简单。
I want to be able to delete multiple records from the database. I have the id
's of all the records I wish to delete. I call the resource.destroy
route using comma separated list of ids (id
is of postgres type uuid
), like so:
我希望能够从数据库中删除多条记录。我有id
要删除的所有记录的's。我resource.destroy
使用逗号分隔的 id 列表(id
属于 postgres 类型uuid
)调用路由,如下所示:
Request URL:http://foo.app/products/62100dd6-7ecf-4870-aa79-4b132e60c904,c4b369f1-d1ef-4aa2-b4df-b9bc300a4ff5
Request Method:DELETE
On the other end, my controller action looks like so:
另一方面,我的控制器操作如下所示:
public function destroy($id)
{
try {
$ids = explode(",", $id);
$org->products()->find($ids)->delete();
}
catch(...) {
}
}
This gives me the following error:
这给了我以下错误:
BadMethodCallException in Macroable.php line 81:
Method delete does not exist.
in Macroable.php line 81
at Collection->__call('delete', array()) in ProductsController.php line 251
at Collection->delete() in ProductsController.php line 251
at ProductsController->destroy('62100dd6-7ecf-4870-aa79-4b132e60c904,c4b369f1-d1ef-4aa2-b4df-b9bc300a4ff5')
I have verified that find()
is returning a collection of products
matching the specified ids.
我已经验证它find()
正在返回products
匹配指定 ID的集合。
What am I missing?
我错过了什么?
PS:
1. The model Product
has several belongsTo
relationships with other models.
2. The product.destroy
code works fine if I pass it a single id
PS:1.模型与其他模型Product
有几个belongsTo
关系。2.product.destroy
如果我传递一个代码,代码工作正常id
EDITI guess, I'm also trying to understand what the difference between:
编辑我想,我也想了解两者之间的区别:
$org->products()->find($ids)->delete()
and
和
$org->products()->whereIn('id', $ids)->get()->delete()
is? From what I see, both find
and get
are returning Collections
是?从我所看到的,find
和get
正在返回Collections
回答by patricus
The issue is that you're calling delete()
on a Collection, which does not have that method.
问题是您正在调用delete()
一个没有该方法的集合。
You have a couple options here.
你有几个选择。
Model Events
模型事件
If you have event listeners for the deleting
/deleted
model events, you will need to make sure the deletion happens in a way that each model is loaded and then deleted.
如果您有deleting
/deleted
模型事件的事件侦听器,则需要确保以每个模型加载然后删除的方式进行删除。
In this case, you can use the destroy
method on the model that takes a list of ids. It will load a new model for each id, and then call delete()
on it. As you mention in a comment, it won't restrict the deletion to only those products in the organization, so you would need to filter out those ids before passing the list into the destroy()
method.
在这种情况下,您可以destroy
在采用 id 列表的模型上使用该方法。它将为每个 id 加载一个新模型,然后调用delete()
它。正如您在评论中提到的,它不会将删除仅限于组织中的那些产品,因此您需要在将列表传递给destroy()
方法之前过滤掉这些 id 。
public function destroy($id)
{
try {
$ids = explode(",", $id);
// intersect the product ids for the org with those passed in
$orgIds = array_intersect($org->products()->lists('id'), $ids);
// now this will only destroy ids associated with the org
\App\Product::destroy($orgIds);
}
catch(...) {
}
}
If you don't particularly like that approach, you will need to iterate your collection of organization products and call delete()
on them individually. You can use a standard foreach
, or you can use the each
method on the collection:
如果您不是特别喜欢这种方法,您将需要迭代您的组织产品集合并delete()
单独调用它们。您可以使用标准foreach
,也可以使用each
集合上的方法:
public function destroy($id)
{
try {
$ids = explode(",", $id);
$org->products()->find($ids)->each(function ($product, $key) {
$product->delete();
});
}
catch(...) {
}
}
No Model Events
没有模型事件
Now, if you don't have any model events that you need to listen for, things are a little easier. In this case, you can just call delete()
on the query builder, and it will go straight to deleting the records without loading any model objects. So, you get cleaner code with better performance:
现在,如果您没有任何需要监听的模型事件,事情就会变得简单一些。在这种情况下,您只需调用delete()
查询构建器,它就会直接删除记录而不加载任何模型对象。因此,您可以获得更清晰的代码和更好的性能:
public function destroy($id)
{
try {
$ids = explode(",", $id);
// call delete on the query builder (no get())
$org->products()->whereIn('id', $ids)->delete();
}
catch(...) {
}
}
回答by Andrés Smerkin
When you use the find method, it will find only a single ID. You should use a whereIn to match multiple ids
当您使用 find 方法时,它只会找到一个 ID。您应该使用 whereIn 来匹配多个 id
public function destroy($id)
{
try {
$ids = explode(",", $id);
$org->products()->whereIn('id', $ids)->get()->delete();
}
catch(...) {
}
}
This way you will find all the products with the given IDs and delete them all.
这样,您将找到具有给定 ID 的所有产品并将其全部删除。
回答by Md. Farhan Sadique Ranok
I also faced this problem. Let $orgs
contains some records as a collection. Now you can easily delete these records using a loop like this-
我也遇到了这个问题。让$orgs
包含一些记录作为集合。现在您可以使用这样的循环轻松删除这些记录-
foreach($orgs as $org)
{
$org->delete();
}