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

时间:2016-01-27 19:15:53

标签: php laravel laravel-5 eloquent laravel-5.1

现在,从我所看到的,应该很简单。

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

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

4 个答案:

答案 0 :(得分:14)

问题是您在没有该方法的Collection上调用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(...) {
    }
}

答案 1 :(得分:2)

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

例如:

模型 for (size_t i = 0; i < pool.size(); i++) { if (pool.at(i) == this) { continue; } DynamicObjects* other = pool.at(i); SScollision = PFG::SphereToSphereCollision(pos, other->GetPosition(), rad, other->GetRadious(), contactPoint); if (SScollision) { glm::vec3 relativeVel = this->GetVelocity() - other->GetVelocity(); float eCof = -(1.0f + 1.0f) * glm::dot(relativeVel, contactPoint); float jLin = eCof / (1.0f / this->GetMass() + 1.0f / other->GetMass()); glm::vec3 collision_impulse_force = jLin * contactPoint / deltaTs; //ClearForces(); AddForce(1.0f / this->GetMass() * collision_impulse_force); //pool.at(otherI)->ClearForces(); other->AddForce(-(1.0f / other->GetMass() * collision_impulse_force)); } }

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(...) {
            }
        }

    }

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

答案 2 :(得分:0)

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

\d+\.\d+\.\w+\.\w+

答案 3 :(得分:-1)

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

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

通过这种方式,您可以找到具有给定ID的所有产品并将其全部删除。