Laravel8 1対1 DBのリレーションを定義しよう


目的

  • LaravelにおけるDBの1対1のリレーション定義方法をまとめる

実施環境

  • ハードウェア環境
項目 情報
OS macOS Catalina(10.15.5)
ハードウェア MacBook Pro (13-inch, 2020, Four Thunderbolt 3 ports)
プロセッサ 2 GHz クアッドコアIntel Core i5
メモリ 32 GB 3733 MHz LPDDR4
グラフィックス Intel Iris Plus Graphics 1536 MB
  • ソフトウェア環境
項目 情報 備考
PHP バージョン 7.4.8 Homebrewを用いてこちらの方法で導入→Mac HomebrewでPHPをインストールする
Laravel バージョン 8.6.0 commposerを用いてこちらの方法で導入→Mac Laravelの環境構築を行う
MySQLバージョン 8.0.19 for osx10.13 on x86_64 Homwbrewを用いてこちらの方法で導入→Mac HomebrewでMySQLをインストールする

前提条件

  • 実施環境に記載されている環境と近い環境が構築されていること。

前提情報

  • 下記コマンドを実行してrelationアプリを作成した。

    $ laravel new relation --auth
    
  • Auth認証で使用されるusersテーブルのIDとリンクするuser_idカラムを有するphone_numbersテーブルがあるとする。両テーブルのカラム情報を下記に記載する。

    • usersテーブル

      Field Type Null Key Default Extra
      id bigint unsigned NO PRI NULL auto_increment
      name varchar(255) NO NULL
      email varchar(255) NO UNI NULL
      email_verified_at timestamp YES NULL
      password varchar(255) NO NULL
      remember_token varchar(100) YES NULL
      created_at timestamp YES NULL
      updated_at timestamp YES NULL
    • phonesテーブル

      Field Type Null Key Default Extra
      id bigint unsigned NO PRI NULL auto_increment
      user_id bigint unsigned NO NULL
      number varchar(255) NO NULL
      created_at timestamp YES NULL
      updated_at timestamp YES NULL
  • 両テーブルのカラムに注目するとわかるようにusersテーブルとphone_numbersテーブルは1対1の関係になっている。(usersテーブルのidとphone_numbersテーブルのuser_id)

  • 前述した1対1のリレーションを定義する。

概要

  1. usersテーブルからphonesテーブルに対するモデルファイルへの定義記載
  2. phonesテーブルからusersテーブルに対するモデルファイルへの定義記載

詳細

  1. usersテーブルからphonesテーブルに対するモデルファイルへの定義記載

    1. アプリ名ディレクトリで下記コマンドを実行してUserモデルファイルを開く。

      $ vi app/Models/User.php
      
    2. 下記のようにリレーションを定義する。

      アプリ名ディレクトリ/app/Models/User.php
      <?php
      
      namespace App\Models;
      
      use Illuminate\Contracts\Auth\MustVerifyEmail;
      use Illuminate\Database\Eloquent\Factories\HasFactory;
      use Illuminate\Foundation\Auth\User as Authenticatable;
      use Illuminate\Notifications\Notifiable;
      
      class User extends Authenticatable
      {
          use HasFactory, Notifiable;
      
          /**
           * The attributes that are mass assignable.
           *
           * @var array
           */
          protected $fillable = [
              'name',
              'email',
              'password',
          ];
      
          /**
           * The attributes that should be hidden for arrays.
           *
           * @var array
           */
          protected $hidden = [
              'password',
              'remember_token',
          ];
      
          /**
           * The attributes that should be cast to native types.
           *
           * @var array
           */
          protected $casts = [
              'email_verified_at' => 'datetime',
          ];
      
          // 下記を追記
          /**
           * ユーザの電話番号を取得
           *
           * @return void
           */
          public function phone()
          {
              return $this->hasOne('App\Models\Phone');
          }
          // 上記までを追記
      }
      
      
    3. アプリ名ディレクトリで下記コマンドを実行してtinkerを起動する。

      $ php artisan tinker
      
    4. tinkerで下記を実行してnull以外が帰ってくることを確認する。(usersテーブルとphonesテーブルにそれぞれデータが格納されているものとする。スペルミスがないのにnullが帰ってきてしまうときはtinkerを再起動する。)

      use App\Models\User;
      User::find(1)->phone;
      
  2. phonesテーブルからusersテーブルに対するモデルファイルへの定義記載

    1. アプリ名ディレクトリで下記コマンドを実行してUserモデルファイルを開く。

      $ vi app/Models/Phone.php
      
    2. 下記のようにリレーションを定義する。

      アプリ名ディレクトリ/app/Models/Phone.php
      <?php
      
      namespace App\Models;
      
      use Illuminate\Database\Eloquent\Factories\HasFactory;
      use Illuminate\Database\Eloquent\Model;
      
      class Phone extends Model
      {
          use HasFactory;
      
          // 下記を追記
          public function user()
          {
              return $this->belongsTo('App\Models\user');
          }
          // 上記までを追記
      }
      
    3. アプリ名ディレクトリで下記コマンドを実行してtinkerを起動する。

      $ php artisan tinker
      
    4. tinkerで下記を実行してnull以外が帰ってくることを確認する。(usersテーブルとphonesテーブルにそれぞれデータが格納されているものとする。スペルミスがないのにnullが帰ってきてしまうときはtinkerを再起動する。)

      use App\Models\Phone;
      User::find(1)->user;
      

超簡単なまとめ

  • 1対1のリレーションはメインテーブル→サブテーブルのときはhasOne(サブテーブルに紐づくモデル名)を使用し、サブテーブル→メインテーブルのときはbelongsTo(メインテーブルに紐づくモデル名)と記載する。

参考文献