Laravel Beziehungen anfügen, wenn nicht schon montiert

Gibt es eine schnelle Möglichkeit der Anbringung Beziehungen, wenn Sie nicht bereits angebracht. Ich bin mit diesem code aktualisieren Beziehungen eines Modells;

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

Aber ich bin immer diese Fehler, die ich bin diesem Fehler;

SQLSTATE[23000]: Integrity constraint violation: 1062 Duplicate entry ‚1-41‘ für Schlüssel ‚PRIMARY‘ (SQL: insert into message_user (message_id, user_id) Werte (1, 41), (1, 42), (1, 43), (1, 44), (1, 45), (1, 46), (1, 47), (1, 48), (1, 49), (1, 50))

Möchte ich vermeiden, gehen durch eine sehr lange Liste von array prüfen, welche Benutzer nicht bereits angebracht, und befestigen Sie Sie. Auch lassen Sie mich wissen, wenn dies der einzige Weg ist.

Ich bin am überlegen so etwas wie;

$message->Users()->attachIfNotAttached($request->get('users'));
  • MySQL unterstützt INSERT IGNORE, aber ich glaube nicht, dass laravel auch nicht.
  • Ich denke, die einzige Lösung ist, zu überprüfen, ob die Beziehung existiert für jeden Benutzer vor der Befestigung.
  • Was gespeichert wird, in $request->get('users')? Benutzer-IDs?
  • $request->get(‚Benutzer‘) ist ein array eine Liste von Benutzer-ids wie [41, 42, 43, 44, 45, 46, 47, 48, 49, 50] aus dem Beispiel oben
InformationsquelleAutor | 2017-07-27

 

3 Replies
  1. 2

    Etwas wie dies funktionieren könnte:

    Bekommen die IDs, die sind bereits angebracht:

    $attachedIds = $message->Users()->whereIn('id', $request->get('users'))->pluck('id');

    Entfernen Sie die angehängte IDs aus dem request-array:

    $newIds = array_diff($request->get('users'), $attachedIds);

    Befestigen Sie die neuen IDs:

    $message->Users()->attach($newIds);
    • Danke. Dies ist, was ich gesucht habe.
  2. 33

    Laravel hat eine eingebaute Methode für diese – syncWithoutDetaching:

    $message->Users()->syncWithoutDetaching($request->get('users'));
    • Das ist die bessere Antwort
    • WEISE bessere Antwort. Die Methode sollte ein alias syncUnique() oder so etwas. syncWithoutDetaching ist nicht gerade intuitiv zu bedienen ist wie seiner Wirkung.
    • dies hat notihng zu tun mit der OP Frage, dies synchronisiert, aber OP will anfügen
    • Diese macht genau das, was der OP will. Es misst alle Benutzer von der Anfrage über die Botschaft, sind nicht noch angebracht. Die „WithoutDetaching“ – Teil stellt sicher, dass keine Benutzer, die nicht in den Anforderungen getrennt wird.
    • Dies ist die beste Antwort bisher
    • Dies kann ein sauberer Ansatz, aber scheint zu langsam, dasyncWithoutDetaching erscheint, um individuelle Datenbank-Schreibvorgänge pro pivot einfügen. attach([1,2,3]) nur eine einfügen. Ich habe zudem nicht das, rein meine Beobachtungen.

  3. 1

    Mit syncWithoutDetaching oder sync([arr], false) sieht sauberer aus, im code, aber führt 25x langsamer als attach(). Dies ist, weil es überprüft jede id und führt die einzelnen Datenbank-inserts pro Artikel.

    Ich würde vorschlagen, aufbauend auf Paul Spiegel die Antwort durch die Erweiterung eloquent oder erstellen Sie eine neue Methode für Ihre model-Klasse.

    In meinem Anwendungsfall habe ich einen Feed Klasse und ein Post Klasse, verbunden durch eine viele zu viele Dreh-und Angelpunkt. Ich fügte hinzu, die folgende Methode, um mein Futter Klasse.

    public function attachUniquePosts($ids)
    {
        $existing_ids = $this->posts()->whereIn('posts.id', $ids)->pluck('posts.id');
        $this->posts()->attach($ids->diff($existing_ids));
    }
    • Anbringen 20 Beiträge in einen feed mit syncWithoutDetaching() nahm durchschnittlich
      0.107 s
    • Anbringen 20 Beiträge in einen feed mit
      attachUniquePosts() nahm durchschnittlich 0.004 s
    • trennen Sie fehlende Elemente in $ids?

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.