この記事でわかること
-
$user->posts()と$user->postsの違い - リレーションメソッド呼び出しについて
- 動的プロパティ呼び出しについて
- Laravelのマジックメソッドについて
user->posts() と$user->postsの違い を簡単にまとめる
-
$user->posts()- 返却されるのはクエリビルダ。
- この書き方をリレーションメソッドという。
-
$user->posts- 返却されるのはモデルインスタンスを格納したコレクションORモデルインスタンス。
- この書き方を動的プロパティ呼び出しという。
リレーションメソッド呼び出しについて
Userモデルに定義されているposts() リレーションで実行されたクエリビルダが返ってきます。
この返却されたオブジェクトをリレーションオブジェクト等といいます。
クエリビルダが返ってくるということは、こういうことができます。
$user->posts()->where('title', 'hoge')->get();
つまり、Eloquentクラスのメソッドが使えるということですね。
また、単純に以下のように書くと
$user->posts();
モデルに定義されてる、リレーションメソッドの返り値の型のオブジェクトが返ってきます。
- HasMany
- HasOne
- BelongsTo
- etc...
上記を総じてリレーションオブジェクトと言います。
注意
リレーションオブジェクトはモデルのインスタンスではありません。
なのでリレーション先のモデルに定義されてるメソッドを呼び出すとエラーになります。
$user->posts()->getImageFullPath();
あくまでクエリビルダが返ってくるので、このオブジェクトでできることはクエリ操作ということですね。
動的プロパティ呼び出しについて
Userモデルに定義されてるposts()リレーションで定義されたクエリが実行され、postsテーブルを指定の条件で検索した結果のpostsテーブルのレコードのモデルインスタンスが帰ってきます。
単一のモデルインスタンスが返ってくるのは
- HasOne
- BelongsTo
などのリレーションで、単一の検索結果になるようなものです。
複数のモデルインスタンスが返ってくる場合は、コレクションでラップされて帰ってきます。
- HasMany
など、複数の検索結果になるようなものです。
返ってくるのは、モデルインスタンスORコレクションなので、こういうことができます。
// リレーション先のモデルのメソッドが呼べる。
$user->posts->getImageFullPath();
// コレクションメソッドが使える。
$user->posts->where('title', 'hoge');
注意
モデルインスタンスORコレクションは、クエリビルダではありません。
なので、Eloquentクラスのメソッドを、メソッドチェーンで呼び出すとエラーになります。
$user->posts->orderBy('created_at');
リレーションメソッドで呼び出されるのは、リレーションメソッドの戻り値の型のリレーションオブジェクト。実態はクエリビルダ。
動的プロパティで呼び出されるのは、呼び出したプロパティと同じ名前のリレーションメソッドの検索結果のモデルインスタンス。
Laravelのマジックメソッドについて
では、どうして動的プロパティ呼び出しが可能になるかということを簡単に説明していきます。
Laravelにはマジックメソッドというメソッドがあります。
以下の2つです。
namespace App\Models;
// 以下はModelを継承していないことに注意
class Person
{
protected array $attributes = [];
// プロパティの値を取得
public function __get(string $key ) : ?mixed
{
if (isset($this->attributes[$key])) {
return $this->attributes[$key];
}
return null;
}
// プロパティを設定
public function __set(string $key, mixed $value)
{
$this->attributes[$key] = $value;
}
// すべてのプロパティをリスト
public function getAttributes(): array
{
return $this->attributes;
}
}
上記の2つのメソッドがEloquentのModelクラス(abstruct)に定義されています。
この2つのメソッドがそれぞれ何をしているかと言うのを簡単に説明していきます。
これはModelクラスに定義されている以下のプロパティを操作するメソッドです。
protected array $attributes = [];
まず__set($key, $value)は何をしているのかと言うと、プロパティとその値を設定しています。
これによって、リレーション先のカラム名を呼び出しても即座に「未定義のプロパティです。」と怒られずに済むのですね。
次に__get($key)が何をしているのかと言うと、あるプロパティ名が来たときプロパティ名があり、値があればその値を返す。プロパティ名がなければnullを返すということをしています。
なので、これも未定義のプロパティを呼んでもnullが返ってくるだけで、「未定義のプロパティです。」と怒られずに済む仕組みの一つですね。
参考記事