Laravel, sync () - Wie synchronisiere ich ein Array und übergebe zusätzliche Pivot-Felder?


77

Die offizielle Laravel-Dokumentation hat folgende sync()Funktion:

$user->roles()->sync( array( 1, 2, 3 ) );

Sie können den angegebenen IDs auch andere Pivot-Tabellenwerte zuordnen:

$user->roles()->sync( array( 1 => array( 'expires' => true ) ) );

Im letzteren Beispiel wird nur eine einzige Pivot-Zeile hinzugefügt. Was ich nicht verstehe, ist, wie ich andere Pivot-Tabellendatensätze zuordnen kann, wenn mehr als eine Zeile synchronisiert werden soll.

Danke im Voraus.


Die Antwort unten hat mich nicht ruhig durchgebracht. Könnten Sie bitte Ihre Lösungen dazu posten? Vielen Dank!
Evis

Gute Frage ... alle Tutorials sind voller Grundlagen.
Shahid Karimi

Antworten:


31

Das funktioniert bei mir

foreach ($photos_array as $photo) {

    //collect all inserted record IDs
    $photo_id_array[$photo->id] = ['type' => 'Offence'];  

}

//Insert into offence_photo table
$offence->photos()->sync($photo_id_array, false);//dont delete old entries = false

2
Upvoting dieses, weil es schön und sauber ist, und ich vermute, dass es für jeden Entwickler, der danach kommt, sehr einfach sein würde, es zu verstehen und zu ändern.
DevBodin

Sie können ersetzen ->sync($photo_id_array, false)zu ->syncWithoutDetaching($photo_id_array)auch. Upvoting auch, da dies die eleganteste Lösung ist.
Musa

141

Um syncmehrere Modelle zusammen mit benutzerdefinierten Pivot-Daten zu erstellen, benötigen Sie Folgendes:

$user->roles()->sync([ 
    1 => ['expires' => true],
    2 => ['expires' => false],
    ...
]);

Dh.

sync([
    related_id => ['pivot_field' => value],
    ...
]);

bearbeiten

Beantwortung des Kommentars:

$speakers  = (array) Input::get('speakers'); // related ids
$pivotData = array_fill(0, count($speakers), ['is_speaker' => true]);
$syncData  = array_combine($speakers, $pivotData);

$user->roles()->sync($syncData);

1
Jarek aber was , wenn ich zum Beispiel habe $speakers = \Input::get( 'speakers' )(wo $ Lautsprecher ein Array werden), und will dann passieren $speakersmit zusammen =>array( 'is_speaker' => true)?
1омица Кораћ

1
Nicht was wenn. Sie erstellen ein Synchronisierungsarray wie oben gezeigt. Erstellen Sie Ihr Array mit idsals Schlüssel oder machen Sie es so in Ihrem HTML-Formular.
Jarek Tkaczyk

Jarek, mein \ Input :: get ('Lautsprecher') gibt ein Array von IDs zurück. Würde so etwas funktionieren:$training->users()->sync( array( $speakers => array( 'is_speaker' => true ) ) )
1омица Кораћ

1
@ JarekTkaczyk Danke! Die Antwort auf den Kommentar war genau das, wonach ich gesucht habe!
Pathros

1
@JarekTkaczyk sieht gut aus, aber jedes Element wird mit einer separaten Abfrage aktualisiert \ eingefügt, was etwas enttäuschend ist, da es die Leistung beeinträchtigt.
Tylik

4

Anbringen / Abnehmen

Eloquent bietet außerdem einige zusätzliche Hilfsmethoden, um die Arbeit mit verwandten Modellen zu vereinfachen. Stellen wir uns zum Beispiel vor, ein Benutzer kann viele Rollen haben und eine Rolle kann viele Benutzer haben. Verwenden Sie die Methode attach, um einem Benutzer eine Rolle zuzuweisen, indem Sie einen Datensatz in die Zwischentabelle einfügen, die die Modelle verknüpft:

$user = App\User::find(1);

$user->roles()->attach($roleId);

Wenn Sie eine Beziehung an ein Modell anhängen, können Sie auch ein Array zusätzlicher Daten übergeben, die in die Zwischentabelle eingefügt werden sollen:

$user->roles()->attach($roleId, ['expires' => $expires]);

Sie können Sync auch verwenden, wenn Sie alte Rollen entfernen und nur die neuen beibehalten möchten, die Sie jetzt anhängen

$user->roles()->sync([1 => ['expires' => $expires], 2 => ['expires' => $expires]);

Das Standardverhalten kann geändert werden, indem als zweites Argument ein 'false' übergeben wird. Dadurch werden die Rollen mit den IDs 1,2,3 verknüpft, ohne die vorhandenen Rollen zu beeinflussen.

In diesem Modus verhält sich die Synchronisierung ähnlich wie die Attach-Methode.

$user->roles()->sync([1 => ['expires' => $expires], 2 => ['expires' => $expires], false);

Referenz: https://laravel.com/docs/5.4/eloquent-relationships


1

Fügen Sie Ihrem Projekt das folgende Merkmal hinzu und hängen Sie es als Merkmal an Ihre Modellklasse an. Dies ist hilfreich, da dadurch Funktionen zur Verwendung mehrerer Drehpunkte hinzugefügt werden. Wahrscheinlich kann jemand dies ein wenig aufräumen und verbessern;)

namespace App\Traits;

trait AppTraits
{
    /**
     * Create pivot array from given values
     *
     * @param array $entities
     * @param array $pivots
     * @return array combined $pivots
     */
    public function combinePivot($entities, $pivots = [])
    {
        // Set array
        $pivotArray = [];
        // Loop through all pivot attributes
        foreach ($pivots as $pivot => $value) {
            // Combine them to pivot array
            $pivotArray += [$pivot => $value];
        }
        // Get the total of arrays we need to fill
        $total = count($entities);
        // Make filler array
        $filler = array_fill(0, $total, $pivotArray);
        // Combine and return filler pivot array with data
        return array_combine($entities, $filler);
    }
}

Modell:

namespace App;

use Illuminate\Database\Eloquent\Model;

class Example extends Model
{
    use Traits\AppTraits;
    // ...
}

Verwendung:

// Get id's
$entities = [1, 2, 3];
// Create pivots
$pivots = [
    'price' => 634,
    'name'  => 'Example name',
];
// Combine the ids and pivots
$combination = $model->combinePivot($entities, $pivots);
// Sync the combination with the related model / pivot
$model->relation()->sync($combination);

1
Ich mag Ihr Denken - es ist besser, es in etwas Wiederverwendbares zu verwandeln, als es beim nächsten Auftreten dieses Problems zu kopieren -, obwohl ich empfehlen würde, es zu einer Hilfsfunktion zu machen, damit es überall und mit jedem Modell verwendet werden kann.
DevBodin

0

Einfach nur anhängen Ihre Felder und ihre Werte zu den Elementen:

$user->roles()->sync([
   1 => ['F1' => 'F1 Updated']
]);

0
$data = array();
foreach ($request->planes as $plan) {
 $data_plan = array($plan => array('dia' => $request->dia[$plan] ) );                
 array_push($data,$data_plan);    
}
$user->planes()->sync($data);

8
Bei der Beantwortung eines alten Beitrags wäre es hilfreich, wenn Sie Ihrer Antwort einen Kontext und nicht nur Code geben könnten, da dies für andere möglicherweise nützlicher wäre.
David Buck

Siehe David Bucks Kommentar. Fügen Sie auch Software- und / oder System- und / oder Bibliotheksversionen hinzu. Nur so kann ein Abstimmen oder Löschen der Antwort verhindert werden.
ZF007
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.