リレーションシップがまだアタッチされていない場合、すばやくアタッチする方法はありますか?このコードを使用してモデルの関係を更新しています。
if (!empty($request->get('roles')) && is_array($request->get('roles'))) {
$message->Roles()->attach($request->get('roles'));
}
if (!empty($request->get('users')) && is_array($request->get('users'))) {
$message->Users()->attach($request->get('users'));
}
しかし、私はこのエラーを受け取っています。
SQLSTATE [23000]:整合性制約違反:1062キー 'PRIMARY'のエントリ '1-41'が重複しています(SQL:insert into
message_user
(message_id
、user_id
)値(1、41)、(1、42)、(1、43)、(1、44)、(1、45)、(1、46)、(1、47)、(1、48 )、(1、49)、(1、50))
まだ接続されていないユーザーの配列チェックの非常に長いリストを調べて、それらを接続することは避けたいです。これが唯一の方法かどうかも教えてください。
私は何かを考えています。
$message->Users()->attachIfNotAttached($request->get('users'));
このような何かがうまくいくかもしれません:
すでに添付されているIDを取得します。
$attachedIds = $message->Users()->whereIn('id', $request->get('users'))->pluck('id');
添付されたIDをリクエスト配列から削除します。
$newIds = array_diff($request->get('users'), $attachedIds);
新しいIDを添付します。
$message->Users()->attach($newIds);
Laravelにはこのための組み込みメソッドがあります- syncWithoutDetaching :
$message->Users()->syncWithoutDetaching($request->get('users'));
syncWithoutDetaching
またはsync([arr], false)
を使用すると、コードはきれいに見えますが、のパフォーマンスはattach()
より25倍遅い 。これは、各IDをチェックし、アイテムごとに個別のデータベース挿入を実行するためです。
雄弁に拡張するか、モデルクラスに新しいメソッドを作成することによって、 Paul Spiegelの回答 を基に構築することをお勧めします。
私の使用例では、多対多のピボットによってリンクされているFeed
クラスとPost
クラスがあります。 Feedクラスに次のメソッドを追加しました。
_public function attachUniquePosts($ids)
{
$existing_ids = $this->posts()->whereIn('posts.id', $ids)->pluck('posts.id');
$this->posts()->attach($ids->diff($existing_ids));
}
_
syncWithoutDetaching()
を使用してフィードに20件の投稿を添付すると、平均0.107秒かかりましたattachUniquePosts()
を使用してフィードに20件の投稿を添付すると、平均0.004秒かかりました