3つのテーブルgarages
、cars
、securities
があります。
証券は1台の車を安全に保つものであり、複数の証券を保有することもできますが、1つの証券で1台の車を安全に保つことができます。ガレージは車があり、証券もあります。
私が欲しいのは、すべての証券をリストし、彼がいるガレージの名前を知ることです。問題は、securities
にはガレージのIDを含む列がなく、安全に保管している車のIDのみがあり、車にはガレージのIDがあるということです。
Laravel EloquentにはhasManyThrough
というメソッドがありますが、securities
にはgarage
からcars
のみがあります。
表は次のとおりです。
ガレージテーブル:
-----------------------------------
|garage_id|garage_name|garage_size|
-----------------------------------
| 1| Garage 1| 200|
-----------------------------------
| 2| Garage 2| 400|
-----------------------------------
車のテーブル:
---------------------------
|car_id|car_name|garage_id|
---------------------------
| 1| Car 1| 1|
---------------------------
| 2| Car 2| 1|
---------------------------
| 3| Car 3| 2|
---------------------------
証券表:
----------------------------------
|security_id|security_name|car_id|
----------------------------------
| 1| Security 1| 1|
----------------------------------
| 2| Security 2| 1|
----------------------------------
| 3| Security 3| 2|
----------------------------------
| 4| Security 4| 3|
----------------------------------
出力は次のとおりでなければなりません。
Security 1 is on Garage 1
Security 2 is on Garage 1
Security 3 is on Garage 1
Security 4 is on Garage 2
そして私にはモデルがあります:
コードはガレージを一覧表示することですが、似たようなものにしたいのですが、証券を一覧表示したいと思います(構造がどのようになっているのかを知るためだけです)。
$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
{
}
そして再び強調するために:セキュリティが安全に保っている車に関連するガレージの名前を持ちたいです。
理解しやすくするために、これを行う場合:
$securities = Securities::with(['cars'])->get();
class Securities extends Eloquent
{
public function cars()
{
return $this->hasOne('cars');
}
}
リレーションとしてcars
テーブルからgarage_id
のみを取得します。本当に欲しいのはガレージの名前です。
[relations:protected] => Array
(
[cars] => Cars Object
(
...
[attributes:protected] => Array
(
...
[car_name] => Car 1
[garage_id] => 1
...
オブジェクトを正しく関連付けていないようです。それを分解しましょう:
Garage
に多くのCar
がある場合、Car
はGarage
に属します。この考えを念頭に置いて進めましょう。
Garage
には多くのCar
がありますCar
には多くのSecurity
がありますSecurity
はCar
に属しますGarage
にはSecurity
を介して多くのCar
がありますEloquentでは、先に進んでそれらのリレーションをたたくことができます。上で投稿したスキーマが与えられれば機能するはずです。
_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');
}
}
_
そしてそれはそれであるはずです。
編集:これらのリレーションの組み合わせを使用して、あるモデルから別のモデルに描画できるパスがある限り、任意のモデルからこれらすべてのリレーションにアクセスできます。たとえば、これをチェックしてください:
_$security = Security::with('car.garage')->first();
_
最初にSecurity
レコードを取得し、その上にCar
関係をロードします。その後、もう1ステップ進み、Garage
モデルの下にロードされたすべてのCar
オブジェクトにすべてのSecurity
関係をロードします。
次の構文を使用してそれらにアクセスできます。
_$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";
}
}
_
さらに、関係オブジェクトはCollection
のインスタンスであるため、->each()
、->count()
、->map()
などのすべての凝ったメソッドを使用できます。
最近、同様の問題に遭遇し、次のようなことができました。
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();
}
}
これにより、証券には1つのガレージ関係があり、次のようなことができます。
$securities = Securities::with('garage')->get();
foreach($securities as $security)
{
echo $security->security_name . ' is on ' . $security->garage->garage_name;
}
これは元の問い合わせに関連しています。
hasOneThroughはLaravel 5.8で利用可能になります