Help us understand the problem. What is going on with this article?

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(メインテーブルに紐づくモデル名)と記載する。

参考文献

miriwo
web系のバックエンドの知識を習得中! 2019/07/07~毎日更新中
https://miriwo.hatenablog.com/
boomtechcafe
埼玉県の朝霞台を拠点にエンジニアの勉強会、交流会等のイベントを企画しています! 朝霞台駅か北朝霞駅が全然行けちゃうぜってエンジニアの方がいたら是非! もくもく会とかゲーム大会とかもやれたらな~って思ってます。
https://boom-teck-cafe.connpass.com/
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away