【laravel】1対多のbelongsTo(hasMany)まとめ。select, insertなどの複数保存や検索も解説

パン田@現役エンジニア
こんにちは!週2エンジニアのぱん田です。
きょうはLaravelのhasManyな関係について、解説しますね!

 

laravelでbelongsToを設定する方法を説明します!

いわゆる1対多をどうやって実装するのかという話しですね。

さらに、select, insertなどの検索と保存についても説明しておきます。

laravelで1対多(belongsTo)を実装する

まずはモデルファイルの設定を。

Userモデルと、Postモデルで説明します。

User hasMany Postな1対多の関係です。

から説明しますね。

※migrationファイルは作れるものとして説明します。
またmigrationファイルでforegin keyを設定しなくとも、この実装で1対多の実装ができます。

まあ、普通は外部キー制約つるのが普通ですけどね。

User.php

<?php

namespace App;

use Illuminate\Notifications\Notifiable;
use Illuminate\Contracts\Auth\MustVerifyEmail as MustVerifyEmail;
use Illuminate\Foundation\Auth\User as Authenticatable;

class User extends Authenticatable implements MustVerifyEmail
{
    use Notifiable;

    /**
     * The attributes that are mass assignable.
     *
     * @var array
     */
    protected $fillable = [
        'name', 'email', 'password', 'avatar',
    ];

    /**
     * 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',
    ];

 
    public function posts()
    {
        return $this->hasMany('App\Post');
    }
}

 

そんでPost.php

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Post extends Model
{
    protected $fillable = [
        'contentl',
        'user_id'
    ];

    // リレーション
    public function user()
    {
        return $this->belongsTo('App\User');
    }
}

 

UserはPostをhasManyな関係です。なのでモデルにこう書きます。

postsと複数形にするのが一般的です。(たぶん単数形でも大丈夫なはず)
userは複数のpostを持っているのでpostsにするわけですね。

public function posts() {
  return $this->hasMany('App\Post');
}

 

これはpostsテーブルにuser_idという名前のカラム(外部キー)が存在する前提です。

もしこれが別の名前だったら、第二引数にreturn $this->hasMany(‘App\Post’, ‘another_user_id’); というようにカラム名を指定します。

逆に、Postモデル側だとこうですね。
メソッド名が単数系なのに注目。postが持っているのは1つの親(user)なので単数形。

public function user() {
   return $this->belongsTo('App\User');
}

 

belongsTo, hasManyなデータにアクセスする方法|select

controllerファイルでbelongsTo, hasManyなデータを安家方法です。

モデルファイルにpostsメソッドを書いてあると、postsプロパティにアクセスできます。

use App\User;
これをお忘れなく。

$user = User::find(1)
$user->posts
foreach($user->posts as $post){
  $post->content
}

SQLでいうとこんな検索をします。

SELECT posts.* FROM posts WHERE posts.user_id = 1

postsテーブルのcontentカラムにアクセスするときは上記のようにforeachしてカラム名のメンバ変数にアクセスします。

簡単ですね!

続いてPostモデルからその所有者であるuserを取得する場合

user App\User; を忘れずに。

$post = Post::find(1);
$post->user->name;

Postモデルにuserメソッドを実装しましたよね?そうするとuserというメンバ変数でアクセスできるみたいです。

簡単ですね!

続いてinser系です。

belongsTo, hasManyなデータをDBに保存する方法|insert

こんな感じです。

Auth::user()->posts()->create($request->all());

 

Auth::user()はApp\Userのインスタンスを返します。モデルですね。

それでAuth::user()->posts()はこのインスタンスを返します。

Illuminate\Database\Eloquent\Relations\HasMany
Laravel5.8公式ドキュメント

はい、ここで間違いやすい注意点です。

postsに()がない下記だとCollectionインスタンスを返します。User::findとかで取得できるアレです。

Auth::user()->posts

これはuserがhasManyなpostをすべて取得するわけです。
今回はcreateしたいので、そうではなくて Auth::user()->posts()にするのです。

公式ドキュメントを見るとわかるのですが、createメソッドがありますね。

引数は配列を取りますので、$request->all()で配列を渡してあげます。

ちなみに、postを1つではなく、複数一気に保存したい場合にはcreateManyメソッドを使いましょう。

引数を、保存したい値の配列を、さらに配列で囲みます。

Auth::user()->posts()->createMany([$request->all()]);

 

こんな感じ。簡単ですね!
今日のところはこんな感じです!

最後に!

あと、エンジニアの年収を上げる方法やフリーの営業法をツイートしてるんでフォローしてくださいっ!!


フォローは↓からですよ!