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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-26 00:19:58  来源:igfitidea点击:

How to delete multiple records using Laravel Eloquent

phplaravellaravel-5eloquentlaravel-5.1

提问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.destroyroute using comma separated list of ids (idis 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 productsmatching the specified ids.

我已经验证它find()正在返回products匹配指定 ID的集合。

What am I missing?

我错过了什么?

PS: 1. The model Producthas several belongsTorelationships with other models. 2. The product.destroycode 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 findand getare returning Collections

是?从我所看到的,findget正在返回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/deletedmodel 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 destroymethod 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 eachmethod 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 $orgscontains some records as a collection. Now you can easily delete these records using a loop like this-

我也遇到了这个问题。让$orgs包含一些记录作为集合。现在您可以使用这样的循环轻松删除这些记录-

foreach($orgs as $org) 
{
    $org->delete();
}