今、これは、私が見ることができるものから、単純なはずでした。
データベースから複数のレコードを削除できるようにしたい。削除するすべてのレコードの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. id
を1つ渡した場合、_product.destroy
_コードは正常に機能します
[〜#〜] edit [〜#〜]おそらく、私は次の違いを理解しようとしています:
_$org->products()->find($ids)->delete()
_
そして
_$org->products()->whereIn('id', $ids)->get()->delete()
_
ですか?私が見るところから、find
とget
の両方が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(...) {
}
}
_
私もこの問題に直面しました。 $orgs
には、いくつかのレコードがコレクションとして含まれています。これで、次のようなループを使用してこれらのレコードを簡単に削除できます-
foreach($orgs as $org)
{
$org->delete();
}
Findメソッドを使用すると、単一のIDのみが検索されます。複数のIDに一致させるにはwhereInを使用する必要があります
public function destroy($id)
{
try {
$ids = explode(",", $id);
$org->products()->whereIn('id', $ids)->get()->delete();
}
catch(...) {
}
}
このようにして、指定されたIDを持つすべての製品を見つけ、それらをすべて削除します。