使用關聯模型的鏈式呼叫時-有無括號的區別

Ruma_z發表於2020-05-24

1、問題:在模型關聯中常常會疑惑例如:$user->addresses() 和 $user->addresses 的區別.

2、歸納與總結:

模型:(一對多)一個使用者多個收貨地址

// 使用者
class User 
{
        public function addresses()
        {
            return $this->hasMany(UserAddress::class);
        }
}
// 收貨地址
class UserAddress 
{
        public function user()
        {
            return $this->belongsTo(User::class);
        }
}
  • 問題: 下面$what1 和 $what2 的區別
    $user = App\Models\User::find(1) //App\Models\User
    $what1 = $user->addresses()  // Illuminate\Database\Eloquent\Relations\HasMany
    $what2 = $user->addresses    // Illuminate\Database\Eloquent\Collection
    要知道上述用法的區別, 就要認識上述的三個類:
  1. App\Models\User
    這個就是常見的模型類,假如我們要訪問使用者的名稱就可以通用 $user->name 這樣訪問屬性的方式來簡單訪問. 因為name這個這個$user例項的一個屬性
  2. Illuminate\Database\Eloquent\Relations\HasMany
    看名稱我們就知道,這是個Eloquent中處理一對多的類;檢視原始碼(下圖)可以看到,HasMany最終是實現了抽象父類Relation,
    而Relation 返回的是一個 叫做 Builder 的例項。 Builder(構造器) 可以簡單的理解為,幫你組裝sql的一個工具類。

使用關聯模型的鏈式呼叫時有無括號的區別

使用關聯模型的鏈式呼叫時有無括號的區別

使用關聯模型的鏈式呼叫時有無括號的區別
所以對於$user->addresses()只是一個構造器。這個構造器並不能直接的幫我們獲取到“使用者所有的收貨地址”的資料。
所以我們可以進行以下操作獲取資料:

$user_addresses = $user->addresses()->get(); //獲取使用者所有的收貨地址  Illuminate\Database\Eloquent\Collection
$user_address   = $user->addresses()->find(1); //獲取該使用者下id=1的收貨地址 App\Models\UserAddresses

3.Illuminate\Database\Eloquent\Collection
這個就可以當作是一個“陣列”, 是Larvel給我們封裝好很多方法的陣列物件。 裡面存在一個items屬性,該屬性裡面包含了上述的模型例項(ps:所以一般返回的“模板引數”裡面都是Model例項和Collection例項。)

使用關聯模型的鏈式呼叫時有無括號的區別
所以我們可以透過以下操作來獲取資料:

$user_addresses  = $user->addresses //獲取使用者下所有的收貨地址 
$user_addresses2 = $user->addresses()->get() // 和上面異曲同工
  • 複習與延申思考
    從收貨地址角度出發,我們再看一看下列每個變數是什麼型別的資料。
    $user_address =  App\Models\UserAddress::find(1);
    $data1 = $user_address->user();
    $data2 = $user_address->user;
    $data3 = $user_address->user()->get();
    $data4 = $user_address->user()->get()->find(1);
    $data5 = $user_address->user()->get()->find(1)->name;
    $data6 = $user_address->user()->first();
    $data7 = $user_address->user()->first()->name;
    $data8 = $user_address->user->name;




    答案
$user_address // App\Models\UserAddress;
$data1 // Illuminate\Database\Eloquent\Relations\BelongsTo;
$data2 // App\Models\User;
$data3 // Illuminate\Database\Eloquent\Collection 即使items只有一個模型;
$data4 // 如果使用者的id為1時--App\Models\User;  不為1時--null
$data5 // 如果使用者的id為1時--顯示使用者的名稱即name屬性; 不為1時系統報錯。
$data6 // App\Models\User;
$data7 // 參照$data5
$data8 // 參照$data5
本作品採用《CC 協議》,轉載必須註明作者和本文連結

相關文章