最近在用 Laravel 5.2,踩了幾個關於 Relation 的坑,記錄一下~~ ...
前段時間比較忙,就沒有堅持寫博客,但發現這周末再想撿起來,好難,一直到了今天晚上,才決定坐下來寫一篇,哈哈哈~~
最近在用 Laravel 5.2,踩了幾個關於 Relation 的坑,在這裡用博客記錄一下。
如果大家不瞭解 Laravel 的 Relation 的話,可以查看文檔Eloquent: Relationships。
在資料庫中先創建兩張表 users 和 password_resets,分別代表用戶和重置密碼,假設他們的關係是一對多,一個用戶有多個重置密碼記錄。
我們可以使用 Laravel 提供的 migration 創建資料庫,具體可以查看文檔Database: Migrations。
使用的users 表和 password_resets 表是預設創建的。
然後我們可以通過界面註冊一個用戶,也可以在 users 表中直接插入一條。password_resets 表中也插入幾條數據,這個也可以通過界面的忘記密碼添加。
然後創建好相應的Model,在 User.php 中,加入如下代碼:
public function passwordReset() {
return $this->hasMany('App\PasswordReset', 'email', 'email');
}
在 Controller 中使用如下代碼:
$data = User::with('passwordReset')->get();
echo $data->toJson();
die;
這個時候你可以看到輸出的數據中的 password_reset 欄位是有內容的,但假如說你希望查找的 password_reset 中只有 token,寫法如下:
$data = User::with(['passwordReset' => function($query) {
$query->select('token');
}])->get();
然後你會驚奇的發現輸出的數據中的 password_reset 欄位是一個空數組。
是不是覺得好神奇,當時我也是崩潰的,去查看源碼,發現原來,Relation 是通過兩條語句實現的,它會先查主表(users表),選出其中關聯的欄位(email欄位)組成數組,使用 in 語句去查詢關聯表(password_resets表),然後將查出來的數據根據關聯欄位相等,處理到一起。這裡需要註意的是查出來的兩塊數據關聯到一起是在 php 中實現的,所以,上面的語句由於沒有查出 password_resets表的 email 欄位,無法關聯到一起,其結果的 password_reset 欄位是一個預設值-空數組。
現在我們在 select 中加入 email 欄位,代碼如下:
$data = User::with(['passwordReset' => function($query) {
$query->select('token', 'email');
}])->get();
然後你就會發現數據中的 password_reset 欄位有值了。
這是踩到的一個坑。
然後我們在來設置一下 PasswordReset.php 中設置一下主鍵,設置為 email 欄位(這裡可能不太合理,email 會重覆,這樣寫只是為了重現這個坑),代碼如下:
protected $primaryKey = 'email';
然後你又會驚奇的發現輸出的數據中的 password_reset 欄位又變成了一個空數組,這又是怎麼了?
原來 Laravel 5.2 為 Model 添加了一個屬性 $keyType,預設值是 int,這意味著它會將查出來的 email 欄位強轉成 int 類型,所以在匹配的時候,就有對不上了。
現在我們只需要在定義一下 $keyType 為 string 就可以了,在 PasswordReset.php 中添加如下代碼:
protected $keyType = 'string';
這是在 Laravel 5.0 升 5.2時踩到的坑。
Laravel 5.2,我也是剛開始看,如果上面有什麼不對的,歡迎大家指出~~
如果大家覺得這篇博客對你有所幫助的話,請點一下頂~~