Laravel Красноречивый фильтр по последней сводной записи

#php #mysql #laravel #orm #eloquent

#php #mysql #laravel #orm #eloquent

Вопрос:

У меня есть 3 таблицы: user , role и сводная user_role . Между пользователем и ролью существует взаимосвязь «многие ко многим».

И еще одна деталь: каждое назначение (роль пользователю) есть timestamp в user_role таблице, поэтому я могу найти, какая роль была недавно добавлена для пользователя.

Есть ли возможность написать запрос eloquent, чтобы получить всех пользователей, которым недавно назначена роль, например, id = 5?

Мне нужно как-то получить последнюю запись из pivot ordered by timestamp , а затем использовать ее в whereHas инструкции. Но как получить эту последнюю запись?

Редактировать

Спасибо за ваши ответы. Но я хотел бы сделать все это немного сложнее. Что, если мы добавим таблицу system , и теперь между system и user будет отношение один ко многим, поэтому пользователь может принадлежать одной системе, а система может иметь несколько пользователей.

И теперь, как получить, например, идентификатор system , который содержит пользователей, имеющих последнюю роль с id = 5 (как в начале).

Ответ №1:

Сначала вам нужно убедиться, что ваши отношения включают временные метки сводки:

 public function users()
{
    return $this->belongsToMany('User')->withTimestamps();
}
  

Затем вы можете использовать следующий запрос в своем коде, чтобы получить всех пользователей, которые недавно получили определенную роль (например, id = 5).

 $role = Role::with(['users', function($query) {
    $query->orderBy('pivot_created_at', 'DESC');
}])->find(5);

// all users with (role_id = 5) ordered by (user_role.created_at DESC)
$users = $role->users;
  

Ответ №2:

Вы можете добавить сводные столбцы в свое отношение, например, так :

 /**
 * The roles that belong to the user.
 */
public function roles()
{
    return $this->belongsToMany('AppRole')->withPivot('timestamp');
}
  

Затем, если вы хотите проверить, есть ли у пользователя определенная роль в последнее время, я бы сделал это

 public function hasRecentRole($roleId, $howRecently = 'last week')
{
     return $this->roles()->where('id', $roleId)->wherePivot('timestamp', '>', new CarbonCarbon($howRecently))->count();
}
  

РЕДАКТИРОВАТЬ: попробуйте что-то вроде этого.

 $systems = System::whereHas('users', function ($query) {
    $query->whereHas('roles', function ($query) {
        $query->where('id', 5)
            ->whereRaw('timestamp = (select max(`timestamp`) from user_roles WHERE user_id = role_user.user_id'));
    });
})->get();
  

Если нет, возможно, вам следует работать поэтапно. Например, получите пользователей с последней ролью 5, затем получите систему, в которой есть хотя бы один из этих пользователей.

Комментарии:

1. Возможно ли получить последнюю запись из сводной записи, упорядоченную по метке времени внутри метода из модели? Итак, я смогу сделать это: System::(‘users.lastRole, function($ q){…}). Это работает для меня, но теперь у меня есть ‘users.roles’, и это дает мне все роли, которые я могу запросить путем закрытия, но теперь мне просто нужно иметь ‘users.lastRole’.

Ответ №3:

Это дает последнему пользователю упорядоченный по timestamp столбцу из user_role таблицы.

 $user->roles()->withPivot('timestamp')->orderBy('user_role.timestamp','desc')->first();
  

Обновить:

 $users=User::with(['system','role'=>function($query)
{
   $query->orderBy('pivot_timestamps','desc');
}])->get();
  

затем это дает системный идентификатор всех пользователей, упорядоченных по временным меткам в сводной таблице.

 foreach($users as $user)
{
      $user->system->id;
}
  

Убедитесь, что у вас есть отношения в user и role model withPivot. , чтобы вы могли использовать pivot_timestamps

 return $this->belongsToMany('users')->withPivot('timestamps');
  

Комментарии:

1. Возможно ли получить последнюю запись из сводной записи, упорядоченную по метке времени внутри метода из модели? Итак, я смогу сделать это: System::(‘users.lastRole, function($ q){…}). Это работает для меня, но теперь у меня есть ‘users.roles’, и это дает мне все роли, которые я могу запросить путем закрытия, но теперь мне просто нужно иметь ‘users.lastRole’.