Abrufen des Werts einer zusätzlichen Pivot-Tabellenspalten-Laravel

71

Ich habe eine Pivot-Tabelle für phone_models, phone_problems und phone_model_phone_problem. Die Pivot-Tabelle hat eine zusätzliche Spalte 'Preis'.

Handy-Modell:

class PhoneModel extends \Eloquent
{
    public function problems()
    {
        return $this->belongsToMany('RL\Phones\Entities\PhoneProblem')->withPivot('price');
    }
}

Telefonproblem:

class PhoneProblem extends \Eloquent
{
    public function models()
    {
        return $this->belongsToMany('PhoneModel')->withPivot('price');
    }
}

Ich versuche, den Preis eines bestimmten Telefons mit einem bestimmten Problem zu ermitteln.

So habe ich es jetzt, aber ich habe das Gefühl, dass Laravel eine eingebaute Eloquent-Funktion hat, die ich nicht viel einfacher finden kann:

$model = $this->phoneService->getModelFromSlug($model_slug);
$problem = $this->phoneService->getProblemFromSlug($problem_slug);

Alles, was dies tut, ist die Auswahl des spezifischen Modells und Problems aus ihrer Schnecke.

dann mache ich mit diesen Anmeldeinformationen den Preis wie folgt:

$row = DB::table('phone_model_phone_problem')
->where('phone_model_id', '=', $model->id)
->where('phone_problem', '=', $problem->id)
->first();

Jetzt kann ich den Preis so bekommen, $row->priceaber ich denke, es muss einen viel einfacheren und "Laravel" Weg geben, dies zu tun.

Rodrigo
quelle

Antworten:

141

Wenn Sie viele zu viele Beziehungen mit Eloquent verwenden, wird dem resultierenden Modell automatisch ein pivotAttribut zugewiesen. Über dieses Attribut können Sie auf Pivot-Tabellenspalten zugreifen. Obwohl standardmäßig nur die Schlüssel im Pivot-Objekt vorhanden sind. Um Ihre Spalten auch dort zu platzieren, müssen Sie sie beim Definieren der Beziehung angeben:

return $this->belongsToMany('Role')->withPivot('foo', 'bar');

Offizielle Dokumente

Wenn Sie weitere Hilfe bei der Konfiguration der Beziehungen zu Eloquent benötigen, lassen Sie es mich wissen.

Bearbeiten

Um den Preis abzufragen, tun Sie dies

$model->problems()->where('phone_problem', $problem->id)->first()->pivot->price
lukasgeiter
quelle
Ich habe meine Frage aktualisiert, damit Sie meine Beziehungen sehen können
Rodrigo
Könnte jemand zeigen, wie eine Pivot-Tabelle basierend auf einer zusätzlichen Spalte abgefragt wird, wie pricein diesem Beispiel von oben$model->problems()->where('phone_problem', $problem->id)->first()->pivot->price
Brent Connor
Wie wäre es, wenn Sie den Wert dieses Pivot-Eintrags nicht erhalten, sondern wie den Preis festlegen?
Bartu
@ Bartu das sollte funktionieren : $model->problems()->updateExistingPivot($problemId, ['price' => $newPrice]). Wenn nicht, stellen Sie bitte eine neue Frage, da die Kommentare nicht wirklich der richtige Ort dafür sind.
lukasgeiter
es funktioniert, vielleicht können Sie es als weitere Referenz für andere Leute hinzufügen.
Bartu
18

So rufen Sie Daten aus der Pivot-Tabelle ab:

$price = $model->problems()->findOrFail($problem->id, ['phone_problem'])->pivot->price;

Oder wenn Sie viele Platten mit unterschiedlichem Preis haben:

$price = $model->problems()->where('phone_problem', $problem->id)->firstOrFail()->pivot->price;

Und dazu.

Um die Daten im Pivot zu aktualisieren, gehen Sie auf NEUEN WEG :

$model->problems()->sync([$problemId => [ 'price' => $newPrice] ], false); 

Wenn der 2. Parameter auf false gesetzt ist, bedeutet dies, dass Sie nicht alle anderen verwandten Modelle trennen.

Oder gehen Sie alten Weg

$model->problems()->updateExistingPivot($problemId, ['price' => $newPrice]);

Und erinnere dich:

So löschen Sie :

$model->problems()->detach($problemId);

So erstellen Sie neue:

$model->problems()->attach($problemId, ['price' => 22]);

Es wurde getestet und hat bewiesen, dass es in Laravel 5.1 funktioniert. Lesen Sie mehr.

Jewgenij Afanasjew
quelle
2
Idealerweise ist es noch besser zu aktualisieren updateExistingPivot(). In Laravel 5.6 ist es auch möglich, die Funktion zu verwenden, anstatt sie falseals zweiten Parameter zu übergeben . sync()syncWithoutDetaching()
Dim13i
3

Laravel 5.8 ~

Wenn Sie ein benutzerdefiniertes Pivot-Modell erstellen möchten, können Sie dies tun:

Account.php

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Account extends Model
{
    public function users()
    {
        return $this->belongsToMany(User::class)
            ->using(AccountUserPivot::class)
            ->withPivot(
                'status',
                'status_updated_at',
                'status_updated_by',
                'role'
            );
    }
}

AccountUserPivot.php

<?php

namespace App;

use Illuminate\Database\Eloquent\Relations\Pivot;

class AccountUserPivot extends Pivot
{
    protected $appends = [
        'status_updated_by_nice',
    ];

    public function getStatusUpdatedByNiceAttribute()
    {
        $user = User::find($this->status_updated_by);

        if (!$user) return 'n/a';

        return $user->name;
    }
}

Im obigen Beispiel Accounthandelt es sich um Ihr normales Modell, und Sie haben $account->usersdie account_userJoin-Tabelle mit Standardspalten account_idund user_id.

Wenn Sie ein benutzerdefiniertes Pivot-Modell erstellen, können Sie den Spalten der Beziehung Attribute und Mutatoren hinzufügen. Wenn Sie im obigen Beispiel das AccountUserPivot-Modell erstellt haben, weisen Sie Ihr Account-Modell an, es über zu verwenden ->using(AccountUserPivot::class).

Dann können Sie auf alles zugreifen, was in den anderen Antworten hier gezeigt wird, aber Sie können auch auf das Beispielattribut über zugreifen $account->user[0]->pivot->status_updated_by_nice(vorausgesetzt, dies status_updated_byist ein Fremdschlüssel für eine ID in der Benutzertabelle).

Weitere Dokumente finden Sie unter https://laravel.com/docs/5.8/eloquent-relationships (und ich empfehle, STRG + F zu drücken und nach "Pivot" zu suchen).

agm1984
quelle
Vielen Dank mein Freund
Ali Sharifineyestani