LaravelEloquentで1対多の関係を構築する方法
このシリーズの前提条件として設定したデモLandingLaravel アプリケーションには、リンクを格納するための単一のデータベーステーブルが含まれています。 このチュートリアルでは、この初期データベース構造を変更して、リンクをリストに編成するために使用する2番目のテーブルを含めます。
このシリーズで使用するリンクとリストの例では、各リンクは1つのリストの一部ですが、各リストには複数のリンクを含めることができます。 この種の関係は、1対多関係とも呼ばれます。
1対多の関係は、タイプ A と呼ばれる1つのアイテムを、タイプ B の複数のアイテムにリンクできる場合に発生しますが、その逆は当てはまりません。 :タイプ B のアイテムは、タイプAのoneアイテムにのみリンクできます。 このシナリオを現在のデモアプリケーションモデルに置き換えると、Aは list
タイプ、Bは link
タイプ。
の作成 LinkList
モデル
開始するには、リンクのリストを表すモデルとデータベーステーブルを作成する必要があります。 次に、既存の Link モデルとテーブルを更新して、両方のモデル間の関係を含めます。 用語 List
PHP内部用に予約されているため、その用語で新しいモデルに名前を付けることはできません。 この新しいモデルと呼ぶことができます LinkList
代わりは。
まず、アプリケーションディレクトリにいることを確認します。
- cd ~/landing-laravel
を使用して新しいモデルを作成します artisan
:
- docker-compose exec app php artisan make:model LinkList
これにより、で新しいモデルクラスが生成されます app/Model
ディレクトリ:
app/Model/LinkList.php
既存のLinkListCLIコマンドの名前を変更する
あなたがあなたを見れば app/Console/Commands
ディレクトリ、あなたはすでにという名前のクラスファイルがあることに気付くでしょう LinkList.php
. これは、作成したばかりのEloquentモデルと混同しないでください。 このクラスには、を介してデータベース内のすべてのリンクを一覧表示するCLIコマンドが含まれています。 artisan
.
将来の混乱を避けるために、今がそのクラスとそのコマンドシグネチャの名前を別の名前に変更する良い機会です。 この場合、クラス名を使用します LinkShow
その名前はクラスが何をするかも説明しているからです。 名前を変更するには app/Console/Commands/LinkList.php
ファイルを別の有効な名前にするには、ターミナルで次のコマンドを実行します。
- mv app/Console/Commands/LinkList.php app/Console/Commands/LinkShow.php
次に、ファイルを開きます app/Console/Commands/LinkShow.php
コードエディタでクラス名をから変更するには LinkList
に LinkShow
、およびからのコマンド署名 link:list
に link:show
、次のコードリストで強調表示されている行のように。 終了すると、ファイルは次のようになります。
<?php
namespace App\Console\Commands;
use App\Models\Link;
use Illuminate\Console\Command;
class LinkShow extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'link:show';
/**
* The console command description.
*
* @var string
*/
protected $description = 'List links saved in the database';
/**
* Create a new command instance.
*
* @return void
*/
public function __construct()
{
parent::__construct();
}
/**
* Execute the console command.
*
* @return int
*/
public function handle()
{
$headers = [ 'id', 'url', 'description' ];
$links = Link::all(['id', 'url', 'description'])->toArray();
$this->table($headers, $links);
return 0;
}
}
完了したら、ファイルを保存して閉じます。 すべてが期待どおりに機能したことを確認するには、新しく名前を変更したものを実行します link:show
職人のコマンド:
- docker-compose exec app php artisan link:show
次のような出力が表示されます。
Output+----+-------------------------------------------------+----------------------------------+
| id | url | description |
+----+-------------------------------------------------+----------------------------------+
| 1 | https://digitalocean.com/community | DigitalOcean Community |
| 2 | https://digitalocean.com/community/tags/laravel | Laravel Tutorias at DigitalOcean |
| 3 | https://digitalocean.com/community/tags/php | PHP Tutorials at DigitalOcean |
+----+-------------------------------------------------+----------------------------------+
LinkListモデルの移行の作成
新しい app/Model/LinkList.php
前に生成したクラス artisan make:model
コマンドには、新しいEloquentクラスの汎用コードが含まれています。 Doctrineなどの他のORMとは異なり、Eloquentはデータベース構造を変更せず、データ自体のみを処理します。 Eloquentモデルは通常リーンであり、クラスプロパティはモデルのテーブル構造から自動的に推測されます。
Eloquentでのみデータを処理するこのアプローチは、 LinkList
クラスは、そのモデルのデータベーステーブル構造から推測されるためです。
構造データベースの操作は通常、データベース移行を介してLaravelで処理されます。 移行により、開発者は、テーブルの作成、変更、削除など、データベースの構造上の変更をプログラムで定義できます。
次に、新しい移行を作成して、データベースにlistsテーブルを設定します。
The artisan
Laravelにデフォルトで含まれているコマンドラインツールには、コントローラー、モデル、移行などの新しいコンポーネントをブートストラップするためのいくつかのヘルパーメソッドが含まれています。 を使用して新しい移行を作成するには artisan
、 走る:
- docker-compose exec app php artisan make:migration create_link_lists_table
Output Created Migration: 2021_07_07_152554_create_link_lists_table
このコマンドは、下に新しいファイルを生成します database/migrations
現在の日時に基づいて自動生成された名前と移行名を使用して、Laravelアプリケーションのディレクトリ。 このファイルには、listsテーブルを設定するために変更する汎用コードが含まれています。
コードエディタを使用して、生成された移行ファイルを開きます。 現在、ファイルは次のようになっています。
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreateLinkListsTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('link_lists', function (Blueprint $table) {
$table->id();
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('link_lists');
}
}
移行は、 up()
で実行されたときのメソッド artisan migrate
指図。 これはあなたのテーブル定義が行くところです、そしてそれはデフォルトでそれを作成します id
主キーフィールドと2つのタイムスタンプフィールド(created_at
と updated_at
)、で定義 timestamps()
スキーマメソッド。 これらのフィールドは、モデルが作成および更新されるときに、それぞれEloquentによって自動的に入力されます。 The down()
移行がロールバックされたときにメソッドが呼び出されます artisan rollback
コマンドを実行し、通常はコードを実行してテーブルを削除するか、構造上の変更を元に戻します。
変更します up
次のフィールドを含める方法:
title
:このリストのタイトルを表す文字列description
:リストの説明を表す文字列slug
:タイトルに基づく一意の短い文字列。通常、ユーザーフレンドリーなURLを作成するために使用されます
1対多の関係では、 many 側(このシナリオではlinks テーブルに対応)は、列参照(または外部キー)を保持する側です。その他の要素(リストテーブルに対応)。 つまり、リンクテーブルをリストテーブルにリンクする参照フィールドを含めるには、後で
一方、 lists テーブルには、リンクを参照するための特別なフィールドは必要ありません。
移行ファイルの現在のコンテンツを次のコードに置き換えます。
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreateLinkListsTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('link_lists', function (Blueprint $table) {
$table->id();
$table->timestamps();
$table->string('title', 60);
$table->string('slug', 60)->unique();
$table->text('description')->nullable();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('link_lists');
}
}
完了したらファイルを保存します。
リンク移行の更新
次に、コードエディタで既存のリンク移行ファイルを開きます。 デモプロジェクトでは、次のパスで移行を見つけることができます。
2020_11_18_165241_create_links_table.php
まず、 use
の完全修飾クラス名を指すディレクティブ LinkList
クラス、ファイルの先頭と最後の直後 use
ライン:
…
use Illuminate\Support\Facades\Schema;
use App\Models\LinkList;
...
次に、テーブル定義に次の行を含めます。 up
メソッドとを設定する行の直後 description
分野:
$table->text('description');
$table->foreignIdFor(LinkList::class);
The foreignIdFor()
メソッドは、参照されるEloquentモデルへの外部キー列を作成します。 デフォルトの命名法を使用して、参照されるテーブルの主キーフィールドにリンクされているフィールドを設定します。
完了したら、完全な移行クラスは次のようになります。
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
use App\Models\LinkList;
class CreateLinksTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('links', function (Blueprint $table) {
$table->id();
$table->string('url', 200);
$table->text('description');
$table->foreignIdFor(LinkList::class);
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('links');
}
}
編集が終了したら、ファイルを保存します。 次に、データベースをワイプしてから、移行コマンドを再度実行して、更新された移行ファイルを使用してデータベース構造を再作成します。
- docker-compose exec app php artisan db:wipe
- docker-compose exec app php artisan migrate
Eloquentモデル関係の構成
これでデータベーステーブルが設定されましたが、それらの間の関係を定義するためにEloquentモデルを構成する必要があります。
に List
関係のone側であるモデル、という名前の新しいメソッドを設定します links
. このメソッドは、プロキシとして機能し、各リストに関連するリンクにアクセスします。 hasMany
親からのメソッド Illuminate\Database\Eloquent\Model
クラス。
コードエディタで、ファイルを開きます app/Model/LinkList.php
. 現在の汎用コードを次のコンテンツに置き換えます。
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class LinkList extends Model
{
use HasFactory;
public function links()
{
return $this->hasMany(Link::class);
}
}
完了したらファイルを保存します。
次に、リレーションシップの many 側を編集して、 List
リンクがそれぞれのリストにアクセスできるようにモデル化します。 これは、 belongsTo
親からのメソッド Model
クラス。 この方法は、1対多の関係の逆辺を定義するために使用されます。
を開きます Link
コードエディタのモデル:
app/Model/Link.php
の現在のコンテンツを置き換えます Link.php
次のコードでファイルします。
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class Link extends Model
{
public function link_list()
{
return $this->belongsTo(LinkList::class);
}
}
完了したらファイルを保存します。
両方のモデルが更新されると、データベースは完全に構成されますが、現在は空です。 このシリーズの次のセクションでは、Eloquentモデルを使用してデータベースに新しいレコードを挿入する方法を学習します。