Laravel 5.5 - 如何使用created_at时间戳查询关注者的通知?

时间:2018-04-10 23:58:32

标签: laravel laravel-5 eloquent laravel-5.5 eager-loading

用户可以是关注者和/或领导者。在这里,userA和userB(两个领导者)在不同时间跟随userC(关注者)(请参阅下面的followers表格了解created_at时间戳。)

为了说明问题,我将首先布置模板:

userX action (year) // template to understand issue below

userC followed userA (2016)
userA added postA/notification (2017)
userC should get notification in feed, since they followed userA a year BEFORE their post

userB added postB/notification (2018)
userC followed userB (2019)
userC should NOT get notification in feed, since they followed userB a year AFTER their post

为了实现这一点,我尝试了这个查询,但它无法正常工作:

$user = App\User::find(3); // follower
$leaders = $user->leaders()
                ->with(['leaderNotifications'=>function($query){
              $query->where('notifications.created_at','>','followers.created_at');
                }])
                ->get();

我认为该问题与created_at无法正确查询有关。以下是在本地查看的确切设置:

1)数据库表名称/数据

users

enter image description here

followers

enter image description here

notifications

enter image description here

2)模特

// User
<?php
namespace App;

use Illuminate\Notifications\Notifiable;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\DatabaseNotification;
use Illuminate\Notifications\DatabaseNotificationCollection;

class User extends Authenticatable {
    use Notifiable;

    // Pivot Table
    public function leaders() {
      return $this->belongsToMany('App\User', ‘followers’, 'follower_id', 'leader_id')
                  ->withPivot('created_at'); // need timestamp to compare against notification timestamp
    }

    public function leaderNotifications() {
        return $this->hasMany(DatabaseNotification::class, 'leader_id')
                    ->orderBy('created_at', 'desc');
    }
}

我正在尝试为当前关注者userC获取正确的通知,这意味着只有新的通知之后他们跟随领导者,而不是领导者的旧通知之前他们跟随当前用户。 同样值得注意的是,最终查询应该能够一次paginate->(20)这些通知,因为它将测试一百万行,因此我们需要确保它高效/可扩展并且可以分页。 对于这个问题,有效/可扩展的查询是什么?

2 个答案:

答案 0 :(得分:2)

以下是我如何解决它,以防其他人:

$user = App\User::find(3); // follower
$leaders = DB::table('notifications')
             ->join('followers','followers.leader_id','=','notifications.leader_id')
             ->where('followers.follower_id', $user->id)
             ->whereRaw('notifications.created_at > followers.created_at')
             ->paginate(20);

无需急切加载或使其复杂化。只需一个简单的DB查询即可处理它!

答案 1 :(得分:1)

  

1)对于Laravel中的原始查询,您应该使用whereRaw

     

2)使用with()时,Laravel首先在两个查询中获取数据   获取父查询的结果,然后使用结果获取with(),   如果要在with闭包中使用第一个查询的数据透视列,则可以   加入。

试试这个:

$user = App\User::find(3); // follower
$leaders = $user
          ->leaders()
          ->with(['leaderNotifications'=>function($query) use ($user){
              $query->whereRaw('notifications.created_at > followers.created_at')
                    ->join('followers','followers.leader_id','=','notifications.leader_id')
                    ->where('followers.follower_id',$user['id']);
                 }])
            ->get();