Ich habe drei Tabellen garages
, cars
, securities
.
Bei den Wertpapieren handelt es sich um diejenigen, die ein Auto sicher halten. Sie können mehr als ein Wertpapier haben, aber ein einzelnes Wertpapier kann nur ein Auto sicher halten. In der Garage steht das Auto und auch die Sicherheiten.
Was ich will, ist, alle Wertpapiere aufzulisten und den Namen der Werkstatt zu kennen, die er ist. Das Problem ist, dass securities
keine Spalte enthält, die die ID der Garage enthält, sondern nur die ID des Autos, das er sicher verwahrt, aber das Auto hat die ID der Garage.
Laravel Eloquent hat eine Methode namens hasManyThrough
, aber securities
hat nur eine garage
bis cars
.
Hier sind die Tabellen:
garagentisch:
-----------------------------------
|garage_id|garage_name|garage_size|
-----------------------------------
| 1| Garage 1| 200|
-----------------------------------
| 2| Garage 2| 400|
-----------------------------------
autos tisch:
---------------------------
|car_id|car_name|garage_id|
---------------------------
| 1| Car 1| 1|
---------------------------
| 2| Car 2| 1|
---------------------------
| 3| Car 3| 2|
---------------------------
wertpapier-Tabelle:
----------------------------------
|security_id|security_name|car_id|
----------------------------------
| 1| Security 1| 1|
----------------------------------
| 2| Security 2| 1|
----------------------------------
| 3| Security 3| 2|
----------------------------------
| 4| Security 4| 3|
----------------------------------
Die Ausgabe muss sein:
Security 1 is on Garage 1
Security 2 is on Garage 1
Security 3 is on Garage 1
Security 4 is on Garage 2
Und ich habe die Modelle:
Der Code ist, die Garagen aufzulisten, aber ich möchte ähnlich machen, aber die Wertpapiere auflisten (nur damit Sie eine Vorstellung davon haben, wie die Struktur ist).
$garages = Garages::with(['cars', 'securities'])->get();
$garages->transform(function($garages) {
return array(
'garage_name' => $garage->garage_name,
'count_cars' => $garage->cars->count(),
'count_securities' => $garage->securities->count(),
);
});
class Garages extends Eloquent
{
public function cars()
{
return $this->hasMany('cars');
}
public function securities()
{
return $this->hasMany('securities');
}
}
class Cars extends Eloquent
{
}
class Securities extends Eloquent
{
}
Und um es noch einmal zu betonen: Ich möchte den Namen der Garage in Bezug auf das Auto haben, das die Sicherheit schützt.
Nur um es noch verständlicher zu machen, wenn ich das mache:
$securities = Securities::with(['cars'])->get();
class Securities extends Eloquent
{
public function cars()
{
return $this->hasOne('cars');
}
}
Ich werde nur den garage_id
Aus der Tabelle cars
als Relationen erhalten. Was ich wirklich will, ist der Name der Garage.
[relations:protected] => Array
(
[cars] => Cars Object
(
...
[attributes:protected] => Array
(
...
[car_name] => Car 1
[garage_id] => 1
...
Es sieht so aus, als würden Sie Objekte nicht richtig in Beziehung setzen. Lassen Sie uns das zusammenfassen:
Wenn eine Garage
viele Car
hat, dann gehört eine Car
zu Garage
, lassen Sie uns mit dieser Idee fortfahren.
Garage
hat viele Car
Car
hat viele Security
Security
Gehört zu Car
Garage
hat viele Security
bis Car
In Eloquent können Sie einfach vorgehen und diese Relationen einklatschen. Dies sollte in Anbetracht des oben angegebenen Schemas funktionieren.
class Garage extends Eloquent
{
public function cars()
{
return $this->hasMany('cars');
}
public function securities()
{
return $this->hasManyThrough('Security', 'Car');
}
}
class Car extends Eloquent
{
public function securities()
{
return $this->hasMany('Security');
}
// ADDED IN SECOND EDIT
public function garage()
{
return $this->belongsTo('Garage');
}
}
class Security extends Eloquent
{
public function car()
{
return $this->belongsTo('Car');
}
}
Und das sollte es sein.
EDIT: Sie können von jedem Modell aus auf alle diese Relationen zugreifen, solange es einen Pfad gibt, den Sie mit einer Kombination dieser Relationen von einem Modell zum anderen zeichnen können. Überprüfen Sie dies zum Beispiel:
$security = Security::with('car.garage')->first();
ruft zuerst die Security
Aufnahme ab und lädt die Car
Beziehung darauf, geht dann einen Schritt weiter und lädt alle Garage
Beziehungen auf jede Car
Objekt geladen unter Security
Modell.
Sie können mit dieser Syntax darauf zugreifen:
$security->car->garage->id
// Other examples
$garage = Garage::with('cars.securities')->first();
foreach($garage->cars as $car)
{
foreach($cars->securities as $security)
{
echo "Car {$car->id} has {$security->id} assigned to it";
}
}
Beachten Sie außerdem, dass die Beziehungsobjekte eine Instanz von Collection
sind, sodass Sie über alle ausgefallenen Methoden wie ->each()
, ->count()
, ->map()
verfügen. verfügbar auf ihnen.
Ich bin kürzlich auf ein ähnliches Problem gestoßen und konnte Folgendes tun:
class Cars extends Eloquent
{
public function garage()
{
return $this->hasOne('Garages');
}
}
class Securities extends Eloquent
{
public function car()
{
return $this->hasOne('Cars');
}
public function garage()
{
return $this->car->garage();
}
}
Dies gibt Ihnen die Securities hat eine Garage Beziehung und Sie können etwas tun wie:
$securities = Securities::with('garage')->get();
foreach($securities as $security)
{
echo $security->security_name . ' is on ' . $security->garage->garage_name;
}
Dies ist relevant für Ihre ursprüngliche Anfrage.
hasOneThrough wird in Laravel 5.8 verfügbar sein