繁体   English   中英

如何使用 Laravel Eloquent 删除多条记录

[英]How to delete multiple records using Laravel Eloquent

现在,从我所见,这应该很简单。

我希望能够从数据库中删除多条记录。 我有我想删除的所有记录的id 我使用逗号分隔的 id 列表( id是 postgres 类型uuid )调用resource.destroy路由,如下所示:

Request URL:http://foo.app/products/62100dd6-7ecf-4870-aa79-4b132e60c904,c4b369f1-d1ef-4aa2-b4df-b9bc300a4ff5
Request Method:DELETE

另一方面,我的控制器操作如下所示:

public function destroy($id)
{
    try {
        $ids = explode(",", $id);
        $org->products()->find($ids)->delete();
    }
    catch(...) {
    }
}

这给了我以下错误:

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')

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

我错过了什么?

PS:1.模型Product与其他模型有几个belongsTo关系。 2. product.destroy代码工作正常,如果我给它传递一个id

编辑我想,我也想了解两者之间的区别:

$org->products()->find($ids)->delete()

$org->products()->whereIn('id', $ids)->get()->delete()

是? 从我所见, findget都在返回Collections

问题是您在没有该方法的集合上调用delete()

你有几个选择。

模型事件

如果您有deleting / deleted模型事件的事件侦听器,您将需要确保以每个模型加载然后删除的方式进行删除。

在这种情况下,您可以在采用 id 列表的模型上使用destroy方法。 它将为每个 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(...) {
    }
}

如果您不是特别喜欢这种方法,您将需要迭代您的组织产品集合并分别对它们调用delete() 您可以使用标准foreach ,也可以使用集合上的each方法:

public function destroy($id)
{
    try {
        $ids = explode(",", $id);
        $org->products()->find($ids)->each(function ($product, $key) {
            $product->delete();
        });
    }
    catch(...) {
    }
}

没有模型事件

现在,如果您没有任何需要监听的模型事件,事情就会变得简单一些。 在这种情况下,您只需在查询构建器上调用delete() ,它将直接删除记录而不加载任何模型对象。 因此,您可以获得更清晰的代码和更好的性能:

public function destroy($id)
{
    try {
        $ids = explode(",", $id);
        // call delete on the query builder (no get())
        $org->products()->whereIn('id', $ids)->delete();
    }
    catch(...) {
    }
}

如果您创建产品模型,它将帮助您完成这些类型的操作。

例如:

模型Products.php

<?php

namespace App\Http\Models;

use Illuminate\Database\Eloquent\Model;

class Products extends Model
{
    /**
     * The table associated with the model.
     *
     * @var string
     */
    protected $table = 'products';
    protected $primaryKey = 'id';

    protected $fillable = ['name', 'price', 'description'];


}

控制器Products.php

您可以使用destroy方法并将一个或多个主键作为参数传递给它。

<?php

    namespace App\Http\Controllers;

    use App\Http\Models\Products;

    class Products 
    {
        
        public function destroy($id)
        {
            try {
                
                $ids = explode(",", $id);
                //$ids is a Array with the primary keys
                Products::destroy($ids);
            }
            catch(...) {
            }
        }

    }

您还可以使用此选项删除带有自定义参数的查询结果

$deletedRows = Products::where('name', 'phones')->delete();

您可以查看 Laravel 文档https://laravel.com/docs/8.x/eloquent#soft-deleting

当您使用 find 方法时,它只会找到一个 ID。 您应该使用 whereIn 来匹配多个 id

public function destroy($id)
{
    try {
        $ids = explode(",", $id);
        $org->products()->whereIn('id', $ids)->get()->delete(); 
    }
    catch(...) {
    }
}

这样,您将找到具有给定 ID 的所有产品并将其全部删除。

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

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM