Laravel——你真的熟悉關聯模型麼?

劍歌丶君發表於2018-05-01

目前只是學習了thinkphplaravel的框架,對於關聯查詢這一塊,更偏愛laravel的寫法,所以這裡就談談我對laravel關聯模型的用法吧。

舉例:使用者與使用者之間的,被關注者與粉絲的關係

簡單而言,一個使用者可以關注多個人,而一個使用者也可以擁有多個粉絲,所以他們之間的關係是屬於多對多的。
不多說,先用資料庫遷移把表創一下。(這裡users的遷移表框架預設有)

$ php artisan make:migration create_followers_table --create="followers"
複製程式碼

開啟剛剛建立的database/migrations/..create_followers_table.php做出如下改動。

.
.
public function up() {
    Schema::create('followers', function(Blueprint $table) {
        $table->increments('id');
        $table->integer('user_id')->index();
        $table->integer('follower_id')->index();
        $table->timestamps();
    });
}
.
.
複製程式碼

遷移表欄位配置好了,執行遷移

php artisan migrate
複製程式碼

資料庫裡就生成了followers表,接下來開始在User模型裡進行編寫關聯關係了。
開啟你的模型user.php

.
.
//一個使用者擁有多個粉絲
public function fans() {
    return $this->belongsToMany(User::class, 'followers', 'user_id', 'follower_id');
}

//一個使用者可以關注多個大佬
public function followings() {
    return $this->belongsToMany(User::class, 'followers', 'follower_id', 'user_id');
}
複製程式碼

這裡解釋一下belongsToMany方法四個引數:
第一個引數是關聯的模型,那肯定是User模型,沒得說。
第二個引數是表名,這裡我的中間表的表名為followers
第三個引數呢,是定在關聯模型的模型外來鍵名。拿第一個fans()通俗的說,是獲取粉絲列表的嘛,那麼當前你是屬於user_id的關係。你不是follower_id
第四個引數呢,則是你要合併的模型外來鍵名,也就是你需要的模型外來鍵名,還是拿fans()方法來說,你是需要關聯來合併查詢到粉絲嘛,所以外來鍵呢就是follower_id

用法:

  1. 比如查詢當前使用者的所有粉絲:
$fans = Auth::user()->fans;
複製程式碼

哇塞,這個是啥意思呀, 其實這個等同於

$fans = Auth::user()->fans()->get();
複製程式碼
  1. 哇,這個人真是大佬,我想要關注她
    先在User.php模型裡有下面的邏輯程式碼:
//模型裡的判斷是否關注的方法
private function isFollowing($user_id) {
    return $this->followings->pluck('id')->contains($user_id);
}
//模型裡的關注方法
public function follow($user_ids) {
    //如果$user_ids不是陣列
    if(!is_array($user_ids)) {
        $user_ids = compact($user_ids); //轉化為陣列
    }
    
    $this->followings()->sync($user_ids, false);
}
複製程式碼

解釋一下上面的兩個方法。
首先,$this->followings和我第 1 點說的一樣,查出當前使用者模型對應的user關注了的所有大佬。
其次用查出來的集合,呼叫集合方法pluck('id')拿出所有id
再繼續呼叫contains($user_id)看是否包含$user_id
這裡皮一下:

return $this->followings->pluck('id')->contains($user_id);
//等價於
return $this->followings->contains($user);
//至於為什麼呢?  因為laravel裡模型會對應到主鍵,我是這麼理解的
複製程式碼

然後這裡有幾條邏輯:

  • 說不定這個大佬是你自己,你肯定患了健忘症。
  • 判斷是否已經關注了她,可能你忘了對吧。
  • 都沒問題,那就關注把。
    根據邏輯在控制器裡寫關注的方法:
public function store(User $user) {
    //說不定這個大佬是你自己,你肯定患了健忘症
    if(Auth::id() === $user->id) {
        return redirect('/');
    }
    //判斷是否已經關注了她,可能你忘了對吧
    if(Auth::user()->isFollowing($user->id)) { //模型裡判斷是否關注的方法
        session()->flash('notice', '你已經關注過他了喲,不需要重複關注');  
        return redirect()->back();
    }
     Auth::user()->follow($user->id); //模型裡的關注方法
    return redirect()->route('users.show', [$user]);    //上面說過模型也是主鍵
}
複製程式碼
  1. 不行,我突然關注錯了,我要取消關注那個人。
    一樣,先在User模型裡寫方法。
public function unfollow($user_ids) {
    //如果不是陣列
    if(!is_array($user_ids)) {
        $user_ids = compact($user_ids);
    }
    
    $this->followings()->detach($user_ids);
}
複製程式碼

然後下面有幾條邏輯:

  • 說不定這個大佬是你自己,你肯定患了健忘症。
  • 你根本就沒關注過別人好嗎
  • 沒問題了,取消關注把
public function destroy(User $user) {
    //說不定這個大佬是你自己,你肯定患了健忘症
    if(Auth::id() === $user->id) {
        return redirect('/');
    }
    //你根本就沒關注過別人好嗎
    if(!Auth::user()->isFollowing($user->id)) {
        session()->flash('notice', '你還沒有關注過他喲,不需要取消關注');  
        return redirect()->back();
    }
    //沒問題了,取消關注吧
    Auth::user()->unfollow($user->id);
    return redirect()->route('users.show', [$user]);
}
複製程式碼

就這樣完成了一個多對多的關聯模型,而且是一個比較特殊的。這個弄懂了,其他的關聯模型,應該就沒啥問題了吧~

相關文章