在 User
模型類中定義一個 lastPost
方法使其與該使用者最新發布的文章記錄建立一對一關聯關係:
public function lastPost()
{
return $this->belongsTo(Post::class);
}
根據 Eloquent 預設使用的外來鍵關聯欄位名稱規則,上面的關聯關係對應的外來鍵欄位應該是 last_post_id(即 users 表中的 last_post_id 對映到 posts 表的 id 欄位建立關聯),如果是常規的關聯關係,需要在 users 表中包含 last_post_id,不過我們要建立的是執行時的動態關聯關係,這個「動態」不依賴於具體的資料表欄位,那要如何在執行時的 users 表中提供這個欄位呢,結合上面的子查詢實現,我們很容易想到,可以通過子查詢動態提供這個欄位。
我們繼續在 User 模型類中新增一個本地查詢作用域 scopeWithLastPost 方法來定義對應的子查詢實現邏輯:
public function scopeWithLastPost($query)
{
return $query->addSelect([
'last_post_id' => Post::select(['id'])
->whereColumn('user_id', 'users.id')
->where('status', Post::STATUS_NORMAL)
->orderByDesc('created_at')
->limit(1)
])->with('lastPost:id,title,user_id,created_at');
}
這裡我們將 posts 表子查詢欄位改為 id,將查詢得到的欄位別名設定為 users 表的 last_post_id,就可以在執行時動態建立 users 表的 last_post_id 欄位了,我們接著在查詢構建器上通過 with(‘lastPost’) 對 lastPost 關聯進行渴求式載入(這裡還指定了關聯查詢的查詢欄位),由於 users 表此時包含了 last_post_id 欄位,也就可以順理成章的進行對應的一對一關聯查詢了,這樣一來,就可以在使用該查詢作用域的 User 模型例項上獲取到與之關聯的 最新發布的一個 Post 模型例項了。
修改 UserController 關聯查詢程式碼如下:
class UserController extends Controller
{
public function index()
{
$columns = ['id', 'name', 'email'];
$users = User::select($columns)->withLastPost()->orderByDesc('id')->paginate(20);
return view('user.index', ['users' => $users]);
}
}
這一次,我們通過查詢作用域獲取動態的 lastPost 關聯關係,列印獲取到的 $users 變數,可以看到資料結構中包含了關聯的 lastPost 關聯物件,即 Post 模型例項:
這一次,我們可以通過 $user->lastPost
物件獲取文章模型上指定的所有查詢欄位,不再是隻能獲取文章標題了
本作品採用《CC 協議》,轉載必須註明作者和本文連結