【Laravel】Vueを使う時のリレーション

2021/07/22に公開

LaravelでVueを使う時のリレーションについて説明します。

マイグレーションファイルを作成

以下のコマンドを入力してマイグレーションファイルを作成します。

php artisan make:migration create_usstocks_table
php artisan make:migration create_markets_table

php artisan make:migrationがコマンド名でcreate_usstocks_tableがファイル名となります。
ちなみにファイル名がusstocksではなくて、create_usstocks_tableなのか?
Laravelのプロジェクトを作成するとデフォルトでマイグレーションファイルがあり、ファイル名の命名規則がcreate_(テーブル名・複数形)_tableとなっています。
それにしたがって作成します。

テーブルのカラムを設定

作成した各マイグレーションファイルにテーブルのカラムを設定します。

usstocksテーブル

usstocksテーブルには以下の3つのカラムを設定します
ticker:ティッカー(米国株の個々の銘柄を識別するためにつけられた記号)
name:銘柄名
market_id:市場ID

create_usstocks_table.php
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreateUsstocksTable extends Migration {
  public function up() {
    Schema::create('usstocks', function (Blueprint $table) {
      $table->string('ticker')->unique()->primary();
      $table->string('name');
      $table->integer('market_id');
    });
  }
  public function down() {
    Schema::dropIfExists('usstocks');
  }
}

7行目のSchema::create内に必要なカラムを設定します。
8行目にはテーブルの主キーとなるtickerをカラム名とします。
通常、主キーは整数を使いますが今回は文字列を主キーとします。
stringは文字列、uniqueは重複しないこと、primaryは主キーを指定しています。
9行目はnameをカラム名としてstringで文字列を指定します。
10行目はリレーションで使うmarket_idをカラム名としてintegerは整数を指定しています。

marketsテーブル

marketsテーブルには以下の2つのカラムを設定します
market_id:市場ID(1・2)
market:市場名(NYSE・NASDAQ)
以下にレコードを設定します。
1:NYSE
2:NASDAQ

create_markets_table.php
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreateUsstocksTable extends Migration {
  public function up() {
    Schema::create('markets', function (Blueprint $table) {
      $table->bigIncrements('market_id');
      $table->string('market')->unique();
    });
  }
  public function down() {
    Schema::dropIfExists('markets');
  }
}

8行目にテーブルの主キーとなるmarket_idをカラム名としてbigIncrementsは主キーを指定しています。
9行目のmarketをカラム名としてstringで文字列を指定します。

Modelの作成

Modelの作成

まずはusstocksテーブルとmarketsテーブルに対応したModelファイルを作成します。
usstocksテーブルに対応したModel名をUsstockとして、marketsテーブルに対応したModel名をMarketとします。

php artisan make:modelがコマンド名でUsstocksがファイル名となります。

php artisan make:model Usstock
php artisan make:model Market

Laravelのプロジェクトを作成するとデフォルトでUserという名前のModelファイルがありファイル名は大文字で始まっています。
それにしたがって作成します。

Modelの設定

リレーションでusstockからmarketへアクセスできるようにする設定します。

Usstock.php
<?php
namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;

class Usstock extends Model {
  // 文字列でプライマリーキーを使用するために必要な設定
  protected $keyType = 'string';
  protected $primaryKey = 'ticker';

  public function market(){
    return $this->belongsTo(Market::class,'market_id','market_id');
  }
}

12行目からmarket関数を作成してbelongsToメソッドを使ってリレーションの設定を記述します。
13行目のbelongsToメソッドの第1引数はMarketクラスを指定します。
第2引数にはusstocksテーブルのmarket_idを指定します。
第3引数には親となるmarketsテーブルのmarket_idを指定します。

他にもhasOnehasManyなどメソッドがありますので以下の日本語リファレンスを参照してください。

https://readouble.com/laravel/8.x/ja/eloquent-relationships.html

9行目と10行目には文字列を主キーを使用する場合には必要になります。
こちらを参考にしてみてください。

https://zenn.dev/zenn/articles/2021-07-04-laravel-string-primarykey

Resourceの作成

Resourceの作成

まずにusstocksテーブルに対応したResourceファイルを作成します。
Vueでデータを受け取るにはJSON形式になっていないと受け取ることができません。
ResourceファイルではそのデータをJSON形式に変換する設定を行います。
usstocksテーブルに対応したResource名をUsstockResourceとします。
marketsテーブルに対応したResourceは必要ないので作成しません。

php artisan make:resourceがコマンド名でUsstockResourceがファイル名となります。

php artisan make:resource UsstockResource

Resourceの設定

<?php
namespace App\Http\Resources;

use Illuminate\Http\Resources\Json\JsonResource;

class UsstockResource extends JsonResource
{
  public function toArray($request) {
    return [
      "ticker" => $this->ticker,
      "name" => $this->name,
      "market" => $this->market,
    ];
  }
}

Controllerの作成

Controllerの作成

usstocksテーブルに対応したControllerファイルを作成します。
usstocksテーブルに対応したController名をUsstockControllerとします。
marketsテーブルに対応したControllerは必要ないので作成しません。

php artisan make:controllerがコマンド名でUsstockControllerがファイル名となります

php artisan make:controller UsstockController

リレーション前のControllerの設定

リレーションを理解するには順序立てて見るとわかりやすいのでリレーションする前の一覧表示を設定します。
11行目ではusstocksテーブルの全データを取得するためallメソッドを使用して、引数$usstocksに代入しています。
12行目では引数$usstocksUsstockResourcecollectionメソッドに渡してJSON形式で出力します。

<?php
namespace App\Http\Controllers\Api;

use App\Http\Controllers\Controller;
use App\Http\Resources\UsstockResource;
use Illuminate\Http\Request;
use App\Models\Usstock;

class UsstockController extends Controller {
  public function index() {
    $usstocks = Usstock::all();
    return UsstockResource::collection($usstocks);
  }
}

リレーションせずに一覧表示したJSON形式ではmarket_idのみが表示されています。

"data":[
  {
    "ticker": "AAPL",
    "name": "アップル",
    "market_id": 2,
  },
]

リレーション後のControllerの設定

次はリレーション後の一覧表示を設定します。
11行目をusstocksテーブルにmarketsテーブルのデータをリレーションするためwithメソッドに前回Usstockモデルで作成したmarket関数を渡してgetで取得して引数$usstocksに代入しています。

<?php
namespace App\Http\Controllers\Api;

use App\Http\Controllers\Controller;
use App\Http\Resources\UsstockResource;
use Illuminate\Http\Request;
use App\Models\Usstock;

class UsstockController extends Controller {
  public function index() {
    $usstocks = Usstock::with('market')->get();
    return UsstockResource::collection($usstocks);
  }
}

リレーション後の一覧表示したJSON形式ではmarketオブジェクト内にmarket_idとmarketが表示されています。

"data": [
  {
    "ticker": "AAPL",
    "name": "アップル",
    "market": {
      "market_id": 2,
      "market": "NASDAQ"
    },
  },
]

以上で取得したJSONデータを渡してVueで使用できるようになりました。
migrationからModelやControllerまで作成してリレーションの設定までできればある程度のWebアプリであれば対応できると思います。
VueだけでなくReactでも使用できるのでバックエンドを作成するリソースとしてLaravelを選択することもありかもしれません。

GitHubで編集を提案

Discussion