どういうことか
Userが複数のPostを持っていて、その最新の1件だけ表示したいとき、公式ドキュメントに従うと
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class User extends Model
{
public function posts()
{
return $this->hasMany('App\Post');
}
}
とhasManyリレーションを定義して
$user->posts()->orderBy('created_at', 'desc')->first();
と書くのが一般的だと思いますが、最新の1件しか要らないことが予め分かっている場合
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class User extends Model
{
public function latestPost()
{
return $this->hasOne('App\Post')
->orderBy('created_at', 'desc');
}
}
とhasOneで定義して
$user->latestPost;
と書くこともできます。
ほんとうか
HasManyクラスのソースとHasOneクラスのソースを見ると、hasManyでは
Illuminate/Database/Eloquent/Relations/HasMany.php
public function getResults()
{
return $this->query->get();
}
となっているのに対し、hasOneでは
Illuminate/Database/Eloquent/Relations/HasOne.php
public function getResults()
{
return $this->query->first() ?: $this->getDefaultFor($this->parent);
}
としているだけですので、Query Builderの使い方としても正しいと言えます。
どうやって使い分けるか
今回のPostsの例でいうと、いずれにせよ一覧表示などを作ると思いますので、hasManyを定義したほうがいいです。
実際の業務で「有効期間内の最新のキャンペーンのみ適用したい」という場面があり、明らかに1件しか使わないのにDB上は古いキャンペーンが残ってしまうので、そのような場合hasOneで定義した方が有効だと思いました。