Overview
リレーショナルデータベースを使用する場合、Eloquet ORM はモデル クラスに対応するテーブルの行としてモデルを保存します。 MongoDB を使用すると、Lambda 統合は、モデル クラスに対応するコレクション内のドキュメントとしてモデルを保存します。
関係を定義するには、適切な関係メソッドを呼び出す関数をモデル クラスに追加します。 この関数を使用すると、関連するモデルを動的プロパティとしてアクセスできます。 動的プロパティを使用すると、モデル上のプロパティにアクセスするのと同じ構文を使用して関連モデルにアクセスできます。
次のセクションでは、Lalavel 統合で利用可能な Lambel Eloquet と MongoDB 固有の関係について説明し、その定義方法と使用方法の例を示します。
One to one relationship, created by using the
hasOne()method and its inverse,belongsTo()One to many relationship, created by using the
hasMany()and its inverse,belongsTo()Many to many relationship, created by using the
belongsToMany()methodEmbedded document pattern, a MongoDB-specific relationship that can represent a one to one or one to many relationship, created by using the
embedsOne()orembedsMany()methodクロスデータベース関係。MongoDB と SQL モデル間の関係を作成する場合に必要です
1 対 1 の関係
モデル間の 1 対 1 の関係は、他の 1 つのタイプのモデル レコードと完全に関連するモデル レコードで構成されます。
1 と 1 の関係を追加すると、Eloquen は 動的プロパティを使用してモデルにアクセスし、モデルのドキュメント ID を関連モデルに保存できるようにします。
Lambda MongoDBでは、hasOne() メソッドまたは belongsTo() メソッドを使用して 1 対 1 の関係を定義できます。
belongsTo()メソッドを使用して関係の逆を追加すると、Eloquet は 動的プロパティを使用してモデルにアクセスできますが、フィールドは追加されません。
1 対 1 の関係の詳細については、Lambel ドキュメントの「 1 から 1 へ 」を参照してください。
1 から 1 の例
HasOnePlanet次のサンプルクラスは、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);
次のサンプル コードは、サンプル クラスで定義されている動的プロパティを使用して関連モデルにアクセスする方法を示しています。
$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 対多の関係の詳細については、Lambel ドキュメントの「 1 から多への 」を参照してください。
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);
次のサンプル コードは、サンプル クラスで定義されている動的プロパティを使用して、関連するモデルにアクセスする方法を示しています。
$planet = Planet::first(); $relatedMoons = $planet->moons; $moon = Moon::first(); $relatedPlanet = $moon->planet;
多対多の関係
多対多の関係は、2 つの異なるモデルタイプ間の関係で構成されており、各タイプのモデルのインスタンスは、他のタイプの複数のインスタンスに関連付けることができます。
Lambda MongoDBでは、関連するクラスの両方に belongsToMany() メソッドを追加することで、多対多の関係を定義できます。
リレーショナルデータベースで多対多の関係を定義すると、Lambda は関係を追跡するためのピボットテーブルを作成します。 Lambda 統合を使用すると、ピボットテーブルの作成が省略され、関連するモデル クラス名から派生したドキュメント フィールドに関連するドキュメント ID が追加されます。
Tip
Lambda 統合ではピボット テーブルの代わりにドキュメント フィールドが使用されるため、 belongsToMany()コンストラクターからピボット テーブル パラメーターを省略するか、 nullに設定します。
Lambel の多対多の関係の詳細については、Lambel ドキュメントの多対多を参照してください。
次のセクションでは、モデル クラス間の多対多の関係を作成する方法の例を示します。
多対多の例
次のサンプルクラスは、 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);
次のサンプル コードは、サンプル クラスで定義されている動的プロパティを使用して、関連するモデルにアクセスする方法を示しています。
$planet = Planet::first(); $explorers = $planet->visitors; $spaceExplorer = SpaceExplorer::first(); $explored = $spaceExplorer->planetsVisited;
埋め込みドキュメント パターン
MongoDB では、埋め込みドキュメント パターンは、外部キー参照を保持する代わりに、関連モデルのデータを親モデルに追加します。 このパターンを使用して、次の要件の 1 つ以上を満たす。
関連するデータを単一のコレクションにまとめて保持
ドキュメントと関連するデータの複数のフィールドに対してアトミックな更新を実行
データの取得に必要な読み取り回数を減らす
Lambda MongoDB では、次のいずれかの方法を追加して埋め込みドキュメントを定義できます。
embedsOne(): 単一のドキュメントを埋め込みembedsMany(): 複数のドキュメントを埋め込み
注意
これらのメソッドは、クエリ ビルダ オブジェクトとは異なる Eloent コレクションを返します。
自動インストール
埋め込みリレーションにアクセスすると、Lambda 統合は埋め込みデータをデフォルトで 、かずのモデルインスタンスではなく、raw オブジェクトとして返します。埋め込みドキュメントが raw オブジェクトとして返される場合、次の動作が適用されます。
idフィールドはObjectId型で、string ではありません。日付フィールドは、形式が設定された文字列ではなく、
UTCDateTimeオブジェクトです。モデル属性のキャスト、メソッド、
toArray()直列化は適用されません。
埋め込みドキュメントをハイライトされたモデル インスタンスとして検索するには、親モデルの $withプロパティに関係名を追加します。このプロパティは、すべてのクエリの関係を自動的にロードすることで、Laravel 統合は埋め込みドキュメントをモデル インスタンスとして機能します。
次の例では、埋め込まれた addresses 関係をロードするために $with を使用する User モデルを定義します。
declare(strict_types=1); namespace App\Models; use MongoDB\Laravel\Eloquent\Model; use MongoDB\Laravel\Relations\EmbedsMany; class User extends Model { protected $with = ['addresses']; public function addresses() { return $this->embedsMany(Address::class); } }
モデルに $with = ['addresses'] が含まれているため、Laravel 統合は埋め込みアドレスを Address モデル インスタンスとして返します。toArray() メソッドは、idフィールドを string として、日付フィールドを形式化された string として直列化します。すべての Address モデル キャストとメソッドも利用できます。
MongoDB 埋め込みドキュメント パターンの詳細については、次の MongoDB Server チュートリアルを参照してください。
次のセクションでは、埋め込みドキュメントパターンの使用方法の例を示します。
埋め込みドキュメントの例
次のサンプルクラスは、EmbedsMany SpaceShipCargoメソッドを使用して、 モデルと モデル間で の 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'; protected $with = ['cargo']; 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);
クロスデータベースの関係
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);