it-swarm.com.de

So löschen Sie mehrere Datensätze mit Laravel Beredt

Nun, das, was ich sehen kann, hätte einfach sein sollen. 

Ich möchte mehrere Datensätze aus der Datenbank löschen können. Ich habe die id von allen Datensätzen, die ich löschen möchte. Ich rufe die resource.destroy-Route mit einer durch Kommas getrennten Liste von IDs auf (id ist vom Typ postgres uuid):

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

Auf der anderen Seite sieht meine Controller-Aktion so aus:

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

Das gibt mir den folgenden Fehler:

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

Ich habe bestätigt, dass find() eine Sammlung von products zurückgibt, die den angegebenen IDs entspricht.

Was vermisse ich?

PS: 1. Das Modell Product hat mehrere belongsTo Beziehungen zu anderen Modellen . 2. Der product.destroy-Code funktioniert gut, wenn ich eine einzelne id übergeben habe.

EDIT Ich denke, ich versuche auch zu verstehen, worin der Unterschied besteht zwischen:

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

und 

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

ist Von dem, was ich sehe, kehren sowohl find als auch getCollections zurück.

7
Code Poet

Das Problem ist, dass Sie delete() für eine Collection aufrufen, die diese Methode nicht hat.

Sie haben hier einige Möglichkeiten.

Modellereignisse

Wenn Sie Ereignis-Listener für die Modellereignisse deleting/deleted haben, müssen Sie sicherstellen, dass der Löschvorgang so erfolgt, dass jedes Modell geladen und anschließend gelöscht wird.

In diesem Fall können Sie die destroy-Methode für das Modell verwenden, das eine Liste mit IDs enthält. Es lädt ein neues Modell für jede ID und ruft dann delete() auf. Wie Sie in einem Kommentar erwähnen, beschränkt sich der Löschvorgang nicht nur auf die Produkte in der Organisation. Daher müssen Sie diese IDs herausfiltern, bevor Sie die Liste an die destroy()-Methode übergeben.

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

Wenn Sie diesen Ansatz nicht besonders mögen, müssen Sie Ihre Sammlung von Organisationsprodukten iterieren und delete() einzeln aufrufen. Sie können einen Standard foreach oder die each-Methode für die Auflistung verwenden:

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

Keine Modellereignisse

Wenn Sie jetzt keine Modellereignisse haben, auf die Sie achten müssen, ist es etwas einfacher. In diesem Fall können Sie einfach delete() im Query Builder aufrufen, und die Datensätze werden sofort gelöscht, ohne Modellobjekte zu laden. So erhalten Sie saubereren Code mit besserer Leistung:

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

Ich war auch mit diesem Problem konfrontiert. $orgs enthält einige Datensätze als Auflistung. Jetzt können Sie diese Datensätze mit einer Schleife wie folgt löschen:

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

Wenn Sie die Find-Methode verwenden, wird nur eine einzige ID gefunden. Sie sollten ein whereIn verwenden, um mehrere IDs abzugleichen

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

Auf diese Weise finden Sie alle Produkte mit den angegebenen IDs und löschen sie alle.

0
Andrés Smerkin