Laravel 關聯模型由於名稱一致性導致的問題

閆肅的部落格發表於2015-03-03

1. 定義關聯模型

在Laravel裡面,我們可以通過定義以下Model來完成關聯查詢。

class MyPost extends Eloquent {
    public function myPostInfo () {
        return $this->hasOne('MyPostInfo');
    }
}

class MyPostInfo extends Eloquent {}

2. 使用關聯模型

這裡myPostInfo()用的是Camel命名規則,但是我們在讀取某一個PostInfo的時候可以用Snake規則。如下面程式碼都是可行的:

$post = MyPost::find(1);
$post_info = $post->myPostInfo; // example 1
$post_info = $post->my_post_info; // example 2

Laravel允許上述兩種方法,但是沒有合理的處理使用兩種命名造成的衝突。

3. 快取失效

如果我們同時使用了上述兩個例子,就會使其中一個快取失效。在Model的relations變數中,快取了已經讀取過的關聯Model,但是當我們用不同規則的名字去讀取的時候,卻會使得前一個快取失效。例如

$post_info = $post->myPostInfo; 
// $post->relations = [‘myPostInfo’ => ..];

$post_info = $post->my_post_info;
// $post->relations = [‘myPostInfo’ => …, ‘my_post_info’ => …];

所以如果不希望快取失效,得在專案中只使用一種命名方法去讀取關係模型。Laravel推薦的是Camel Case.

4. toArray() 方法失效

如果同時使用了兩者,另外一個問題就是導致Model::toArray()失效。因為toArray()方法首先去relations中查詢Snake Case命名的關聯模型,沒有的話才去看Camel Case的。

所以如果用到了toArray()方法來轉換Model,切忌同時使用兩者。

5. 容易犯錯的位置

最容易犯錯的程式碼是這樣的:

MyPost::with(‘myPostInfo’)->get();

在使用With去eagerLoad關聯模型時,必須使用和定義方法同名的key去讀取,那麼這樣讀取出來的方法只能是Camel Case的key。其他地方就只能用

$my_post->myPostInfo;

來保證不出問題。

相關文章