Eloquentモデル関係
項目一覧
Overview
リレーショナルデータベースを使用する場合、Eloquet ORM はモデル クラスに対応するテーブルの行としてモデルを保存します。 MongoDB を使用すると、Lambda 統合は、モデル クラスに対応するコレクション内のドキュメントとしてモデルを保存します。
関係を定義するには、適切な関係メソッドを呼び出す関数をモデル クラスに追加します。 この関数を使用すると、関連するモデルを動的プロパティとしてアクセスできます。 動的プロパティを使用すると、モデル上のプロパティにアクセスするのと同じ構文を使用して関連モデルにアクセスできます。
次のセクションでは、Lalavel 統合で利用可能な Lambel Eloquet と MongoDB 固有の関係について説明し、その定義方法と使用方法の例を示します。
1 対 1 の関係。
hasOne()
メソッドとその逆のbelongsTo()
を使用して作成1 対多の関係。
hasMany()
とその逆のbelongsTo()
を使用して作成多対多の関係。
belongsToMany()
メソッドを使用して作成埋め込みドキュメント パターン : MongoDB 固有の関係で、1 対 1 または 1 対多の関係を表すことができ、 メソッドまたは メソッドを使用して作成されます。
embedsOne()
embedsMany()
クロスデータベース関係。MongoDB と SQL モデル間の関係を作成する場合に必要です
1 対 1 の関係
モデル間の 1 対 1 の関係は、他の 1 つのタイプのモデル レコードと完全に関連するモデル レコードで構成されます。
1 と 1 の関係を追加すると、Eloquen は 動的プロパティを使用してモデルにアクセスし、モデルのドキュメント ID を関連モデルに保存できるようにします。
Lambda MongoDBでは、hasOne()
メソッドまたは belongsTo()
メソッドを使用して 1 対 1 の関係を定義できます。
belongsTo()
メソッドを使用して関係の逆を追加すると、Eloquet は 動的プロパティを使用してモデルにアクセスできますが、フィールドは追加されません。
1 対 1 の関係の詳細については、Lalas ドキュメントの「One to One 」を参照してください。
1 から 1 の例
HasOne
Planet
次のサンプルクラスは、Orbit
メソッドを使用して、 モデルと モデル間で の 1 対 1hasOne()
の関係を定義する方法を示しています。
declare(strict_types=1); namespace App\Models; use MongoDB\Laravel\Eloquent\Model; use MongoDB\Laravel\Relations\HasOne; class Planet extends Model { protected $connection = 'mongodb'; public function orbit(): HasOne { return $this->hasOne(Orbit::class); } }
次のサンプルクラスは、 belongsTo()
メソッドを使用して、 Orbit
とPlanet
の間の逆BelongsTo
関係を定義する方法を示しています。
declare(strict_types=1); namespace App\Models; use MongoDB\Laravel\Eloquent\Model; use MongoDB\Laravel\Relations\BelongsTo; class Orbit extends Model { protected $connection = 'mongodb'; public function planet(): BelongsTo { return $this->belongsTo(Planet::class); } }
次のサンプル コードは、各クラスのモデルをインスタンス化し、それら間の関係を追加する方法を示しています。 コードの実行によって作成されたデータを確認するには、 VIEW OUTPUTボタンをクリックします。
$planet = new Planet(); $planet->name = 'Earth'; $planet->diameter_km = 12742; $planet->save(); $orbit = new Orbit(); $orbit->period = 365.26; $orbit->direction = 'counterclockwise'; $planet->orbit()->save($orbit);
// Document in the "planets" collection { _id: ObjectId('65de67fb2e59d63e6d07f8b8'), name: 'Earth', diameter_km: 12742, // ... } // Document in the "orbits" collection { _id: ObjectId('65de67fb2e59d63e6d07f8b9'), period: 365.26, direction: 'counterclockwise', planet_id: '65de67fb2e59d63e6d07f8b8', // ... }
次のサンプル コードは、サンプル クラスで定義されている動的プロパティを使用して関連モデルにアクセスする方法を示しています。
$planet = Planet::first(); $relatedOrbit = $planet->orbit; $orbit = Orbit::first(); $relatedPlanet = $orbit->planet;
1 対多の関係
モデル間の 1 対多の関係は、親であるモデルと、関連する子モデル レコードの 1 つ以上で構成されます。
1 対多の関係メソッドを追加すると、Eloquen は 動的プロパティを使用してモデルにアクセスし、親モデルのドキュメント ID を各子モデル ドキュメントに保存できます。
MongoDBでは、親クラスに hasMany()
メソッドを追加し、オプションで子クラスに belongsTo()
メソッドを追加することで、1 対多の関係を定義できます。
belongsTo()
メソッドを使用して関係の逆を追加すると、Eloquen はフィールドを追加せずに 動的プロパティ を使用して親モデルにアクセスできるようになります。
1 対多の関係の詳細については、「 1 対多 」を参照してください Lambda のドキュメント。
1 対多の例
次のサンプルクラスは、 hasMany()
メソッドを使用して、 Planet
親モデルとMoon
子モデル間でHasMany
の 1 対多関係を定義する方法を示しています。
declare(strict_types=1); namespace App\Models; use MongoDB\Laravel\Eloquent\Model; use MongoDB\Laravel\Relations\HasMany; class Planet extends Model { protected $connection = 'mongodb'; public function moons(): HasMany { return $this->hasMany(Moon::class); } }
次のサンプル クラスは、 belongsTo()
メソッドを使用して、 Moon
子モデルとPlanet
親モデルの間で逆のBelongsTo
関係を定義する方法を示しています。
declare(strict_types=1); namespace App\Models; use MongoDB\Laravel\Eloquent\Model; use MongoDB\Laravel\Relations\BelongsTo; class Moon extends Model { protected $connection = 'mongodb'; public function planet(): BelongsTo { return $this->belongsTo(Planet::class); } }
次のサンプル コードは、各クラスのモデルをインスタンス化し、それら間の関係を追加する方法を示しています。 コードの実行によって作成されたデータを確認するには、[ VIEW OUTPUT ] ボタンをクリックします。
$planet = new Planet(); $planet->name = 'Jupiter'; $planet->diameter_km = 142984; $planet->save(); $moon1 = new Moon(); $moon1->name = 'Ganymede'; $moon1->orbital_period = 7.15; $moon2 = new Moon(); $moon2->name = 'Europa'; $moon2->orbital_period = 3.55; $planet->moons()->save($moon1); $planet->moons()->save($moon2);
// Parent document in the "planets" collection { _id: ObjectId('65dfb0050e323bbef800f7b2'), name: 'Jupiter', diameter_km: 142984, // ... } // Child documents in the "moons" collection [ { _id: ObjectId('65dfb0050e323bbef800f7b3'), name: 'Ganymede', orbital_period: 7.15, planet_id: '65dfb0050e323bbef800f7b2', // ... }, { _id: ObjectId('65dfb0050e323bbef800f7b4'), name: 'Europa', orbital_period: 3.55, planet_id: '65dfb0050e323bbef800f7b2', // ... } ]
次のサンプル コードは、サンプル クラスで定義されている動的プロパティを使用して、関連するモデルにアクセスする方法を示しています。
$planet = Planet::first(); $relatedMoons = $planet->moons; $moon = Moon::first(); $relatedPlanet = $moon->planet;
多対多の関係
多対多の関係は、2 つの異なるモデルタイプ間の関係で構成されており、各タイプのモデルのインスタンスは、他のタイプの複数のインスタンスに関連付けることができます。
Lambda MongoDBでは、関連するクラスの両方に belongsToMany()
メソッドを追加することで、多対多の関係を定義できます。
リレーショナルデータベースで多対多の関係を定義すると、Lambda は関係を追跡するためのピボットテーブルを作成します。 Lambda 統合を使用すると、ピボットテーブルの作成が省略され、関連するモデル クラス名から派生したドキュメント フィールドに関連するドキュメント ID が追加されます。
Tip
Lambda 統合ではピボット テーブルの代わりにドキュメント フィールドが使用されるため、 belongsToMany()
コンストラクターからピボット テーブル パラメーターを省略するか、 null
に設定します。
Lambda の多対多の関係の詳細については、「 多対多 」を参照してください。 Lambda のドキュメント。
次のセクションでは、モデル クラス間の多対多の関係を作成する方法の例を示します。
多対多の例
次のサンプルクラスは、 belongsToMany()
メソッドを使用して、 Planet
とSpaceExplorer
モデル間でBelongsToMany
の多対多の関係を定義する方法を示しています。
declare(strict_types=1); namespace App\Models; use MongoDB\Laravel\Eloquent\Model; use MongoDB\Laravel\Relations\BelongsToMany; class Planet extends Model { protected $connection = 'mongodb'; public function visitors(): BelongsToMany { return $this->belongsToMany(SpaceExplorer::class); } }
次のサンプルクラスは、BelongsToMany
SpaceExplorer
メソッドを使用して、 モデルとPlanet
モデル間で逆 多対多の関係を定義する方法を示しています。belongsToMany()
declare(strict_types=1); namespace App\Models; use MongoDB\Laravel\Eloquent\Model; use MongoDB\Laravel\Relations\BelongsToMany; class SpaceExplorer extends Model { protected $connection = 'mongodb'; public function planetsVisited(): BelongsToMany { return $this->belongsToMany(Planet::class); } }
次のサンプル コードは、各クラスのモデルをインスタンス化し、それら間の関係を追加する方法を示しています。 コードの実行によって作成されたデータを確認するには、[ VIEW OUTPUT ] ボタンをクリックします。
$planetEarth = new Planet(); $planetEarth->name = 'Earth'; $planetEarth->save(); $planetMars = new Planet(); $planetMars->name = 'Mars'; $planetMars->save(); $planetJupiter = new Planet(); $planetJupiter->name = 'Jupiter'; $planetJupiter->save(); $explorerTanya = new SpaceExplorer(); $explorerTanya->name = 'Tanya Kirbuk'; $explorerTanya->save(); $explorerMark = new SpaceExplorer(); $explorerMark->name = 'Mark Watney'; $explorerMark->save(); $explorerJeanluc = new SpaceExplorer(); $explorerJeanluc->name = 'Jean-Luc Picard'; $explorerJeanluc->save(); $explorerTanya->planetsVisited()->attach($planetEarth); $explorerTanya->planetsVisited()->attach($planetJupiter); $explorerMark->planetsVisited()->attach($planetEarth); $explorerMark->planetsVisited()->attach($planetMars); $explorerJeanluc->planetsVisited()->attach($planetEarth); $explorerJeanluc->planetsVisited()->attach($planetMars); $explorerJeanluc->planetsVisited()->attach($planetJupiter);
// Documents in the "planets" collection [ { _id: ObjectId('65e1043a5265269a03078ad0'), name: 'Earth', // ... space_explorer_ids: [ '65e1043b5265269a03078ad3', '65e1043b5265269a03078ad4', '65e1043b5265269a03078ad5' ], }, { _id: ObjectId('65e1043a5265269a03078ad1'), name: 'Mars', // ... space_explorer_ids: [ '65e1043b5265269a03078ad4', '65e1043b5265269a03078ad5' ] }, { _id: ObjectId('65e1043b5265269a03078ad2'), name: 'Jupiter', // ... space_explorer_ids: [ '65e1043b5265269a03078ad3', '65e1043b5265269a03078ad5' ] } ] // Documents in the "space_explorers" collection [ { _id: ObjectId('65e1043b5265269a03078ad3'), name: 'Tanya Kirbuk', // ... planet_ids: [ '65e1043a5265269a03078ad0', '65e1043b5265269a03078ad2' ] }, { _id: ObjectId('65e1043b5265269a03078ad4'), name: 'Mark Watney', // ... planet_ids: [ '65e1043a5265269a03078ad0', '65e1043a5265269a03078ad1' ] }, { _id: ObjectId('65e1043b5265269a03078ad5'), name: 'Jean-Luc Picard', // ... planet_ids: [ '65e1043a5265269a03078ad0', '65e1043a5265269a03078ad1', '65e1043b5265269a03078ad2' ] } ]
次のサンプル コードは、サンプル クラスで定義されている動的プロパティを使用して、関連するモデルにアクセスする方法を示しています。
$planet = Planet::first(); $explorers = $planet->visitors; $spaceExplorer = SpaceExplorer::first(); $explored = $spaceExplorer->planetsVisited;
埋め込みドキュメント パターン
MongoDB では、埋め込みドキュメント パターンは、外部キー参照を保持する代わりに、関連モデルのデータを親モデルに追加します。 このパターンを使用して、次の要件の 1 つ以上を満たす。
関連するデータを単一のコレクションにまとめて保持
ドキュメントと関連するデータの複数のフィールドに対してアトミックな更新を実行
データの取得に必要な読み取り回数を減らす
Lambda MongoDB では、次のいずれかの方法を追加して埋め込みドキュメントを定義できます。
embedsOne()
: 単一のドキュメントを埋め込みembedsMany()
: 複数のドキュメントを埋め込み
注意
これらのメソッドは、クエリ ビルダ オブジェクトとは異なる Eloent コレクションを返します。
MongoDB 埋め込みドキュメント パターンの詳細については、次の MongoDB Server チュートリアルを参照してください。
次のセクションでは、埋め込みドキュメントパターンの使用方法の例を示します。
埋め込みドキュメントの例
次のサンプルクラスは、EmbedsMany
SpaceShip
Cargo
メソッドを使用して、 モデルと モデル間で の 1embedsMany()
対多の関係を定義する方法を示しています。
declare(strict_types=1); namespace App\Models; use MongoDB\Laravel\Eloquent\Model; use MongoDB\Laravel\Relations\EmbedsMany; class SpaceShip extends Model { protected $connection = 'mongodb'; public function cargo(): EmbedsMany { return $this->embedsMany(Cargo::class); } }
埋め込みモデル クラスでは、次のCargo
モデル クラスに示すように、関係の定義が省略されています。
declare(strict_types=1); namespace App\Models; use MongoDB\Laravel\Eloquent\Model; class Cargo extends Model { protected $connection = 'mongodb'; }
次のサンプル コードは、 SpaceShip
モデルを作成し、複数のCargo
モデルと、コードの実行によって作成された MongoDB ドキュメントを埋め込む方法を示しています。 コードの実行によって作成されたデータを確認するには、 VIEW OUTPUTボタンをクリックします。
$spaceship = new SpaceShip(); $spaceship->name = 'The Millenium Falcon'; $spaceship->save(); $cargoSpice = new Cargo(); $cargoSpice->name = 'spice'; $cargoSpice->weight = 50; $cargoHyperdrive = new Cargo(); $cargoHyperdrive->name = 'hyperdrive'; $cargoHyperdrive->weight = 25; $spaceship->cargo()->attach($cargoSpice); $spaceship->cargo()->attach($cargoHyperdrive);
// Document in the "space_ships" collection { _id: ObjectId('65e207b9aa167d29a3048853'), name: 'The Millenium Falcon', // ... cargo: [ { name: 'spice', weight: 50, // ... _id: ObjectId('65e207b9aa167d29a3048854') }, { name: 'hyperdrive', weight: 25, // ... _id: ObjectId('65e207b9aa167d29a3048855') } ] }
クロスデータベースの関係
Lambda MongoDB の クロスデータベース関係 とは、リレーショナルデータベースに保存されているモデルと MongoDB データベースに保存されているモデルとの間の関係です。
クロスデータベースの関係を追加すると、Eloquet は 動的プロパティを使用して関連するモデルにアクセスできるようにします。
Lambda 統合は、次のデータベース間の関係メソッドをサポートしています。
hasOne()
hasMany()
belongsTo()
クロスデータベース関係を定義するには、関係データベースに保存されている クラスにMongoDB\Laravel\Eloquent\HybridRelations
パッケージをインポートする必要があります。
次のセクションでは、データベース間の関係を定義する方法の例を示します。
クロスデータベース関係の例
次のサンプルクラスは、リレーショナルデータベースに保存されているSpaceShip
モデルと MongoDB database に保存されているPassenger
モデルとの間でHasMany
の関係を定義する方法を示しています。
declare(strict_types=1); namespace App\Models; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Relations\HasMany; use MongoDB\Laravel\Eloquent\HybridRelations; class SpaceShip extends Model { use HybridRelations; protected $connection = 'sqlite'; public function passengers(): HasMany { return $this->hasMany(Passenger::class); } }
次のサンプルクラスは、 belongsTo()
メソッドを使用して、 Passenger
モデルとSpaceship
モデルの間で逆のBelongsTo
関係を定義する方法を示しています。
declare(strict_types=1); namespace App\Models; use Illuminate\Database\Eloquent\Relations\BelongsTo; use MongoDB\Laravel\Eloquent\Model; class Passenger extends Model { protected $connection = 'mongodb'; public function spaceship(): BelongsTo { return $this->belongsTo(SpaceShip::class); } }
Tip
関係データベースのテーブル スキーマで定義されているプライマリキーが、モデルで使用されているプライマリキーと一致していることを確認します。 Lambda のプライマリキーとスキーマ定義の詳細については、 Lambda ドキュメントの次のページを参照してください。
次のサンプル コードは、MySQL データベースにSpaceShip
モデルを作成し、MongoDB データベースに関連するPassenger
モデルを作成する方法と、コードの実行によって作成されたデータを示しています。 コードの実行によって作成されたデータを確認するには、 VIEW OUTPUTボタンをクリックします。
$spaceship = new SpaceShip(); $spaceship->id = 1234; $spaceship->name = 'Nostromo'; $spaceship->save(); $passengerEllen = new Passenger(); $passengerEllen->name = 'Ellen Ripley'; $passengerDwayne = new Passenger(); $passengerDwayne->name = 'Dwayne Hicks'; $spaceship->passengers()->save($passengerEllen); $spaceship->passengers()->save($passengerDwayne);
-- Row in the "space_ships" table +------+----------+ | id | name | +------+----------+ | 1234 | Nostromo | +------+----------+ // Document in the "passengers" collection [ { _id: ObjectId('65e625e74903fd63af0a5524'), name: 'Ellen Ripley', space_ship_id: 1234, // ... }, { _id: ObjectId('65e625e74903fd63af0a5525'), name: 'Dwayne Hicks', space_ship_id: 1234, // ... } ]