Laravel 5 с максимальной нагрузкой

У меня есть две таблицы, например «users» и «users_actions», где «users_actions» имеет отношение hasMany с пользователями:

пользователи

id | name | surname | email... 

действия

 id | id_action | id_user | log | created_at 

Модель Users.php

 class Users { public function action() { return $this->hasMany('Action', 'user_id')->orderBy('created_at', 'desc'); } } 

Теперь я хочу получить список всех пользователей с их действием LAST .

Я видел, что выполнение Users::with('action')->get(); может легко дать мне последнее действие, просто выбрав только первый результат отношения:

 foreach ($users as $user) { echo $user->action[0]->description; } 

но я хотел избежать этого, конечно, и просто выбрать ТОЛЬКО ПОСЛЕДНИЕ действия для каждого пользователя.

Я попытался использовать ограничение, например

 Users::with(['action' => function ($query) { $query->orderBy('created_at', 'desc') ->limit(1); }]) ->get(); 

но это дает мне неправильный результат, так как Laravel выполняет этот запрос:

 SELECT * FROM users_actions WHERE user_id IN (1,2,3,4,5) ORDER BY created_at LIMIT 1 

что, конечно, неправильно. Есть ли возможность получить это без выполнения запроса для каждой записи с использованием Eloquent? Я делаю какую-то очевидную ошибку, которую я не вижу? Я совершенно новичок в использовании Eloquent, и иногда отношения меня беспокоят.

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

Часть из репрезентативной цели, мне также нужна эта функция для поиска внутри отношения , например, например, я хочу искать пользователей, где LAST ACTION = 'something'

Я попытался использовать

 $actions->whereHas('action', function($query) { $query->where('id_action', 1); }); 

но это дает мне ВСЕ пользователи, у которых было действие = 1, и поскольку это журнал, каждый прошел этот шаг.

Изменить 2:

Благодаря @berkayk, похоже, я решил первую часть моей проблемы, но все же я не могу искать в этом отношении.

 Actions::whereHas('latestAction', function($query) { $query->where('id_action', 1); }); 

все еще не выполняет правильный запрос, он генерирует что-то вроде:

 select * from `users` where (select count(*) from `users_action` where `users_action`.`user_id` = `users`.`id` and `id_action` in ('1') ) >= 1 order by `created_at` desc 

Мне нужно получить запись, где последнее действие – 1

Мое решение, связанное с @berbayk, классно, если вы хотите легко получить последнюю hasMany связанную модель.

Тем не менее, он не мог решить другую часть того, о чем вы просите, поскольку запрос этого отношения с предложением where приведет к тому, что вы уже испытали, – все строки будут возвращены, только latest не будут последними на самом деле (но последнее совпадение с тем, где ограничение).

Итак, вот вы идете:

простой способполучить все и фильтровать коллекцию :

 User::has('actions')->with('latestAction')->get()->filter(function ($user) { return $user->latestAction->id_action == 1; }); 

или сложный путьсделайте это в sql (предполагая MySQL):

 User::whereHas('actions', function ($q) { // where id = (..subquery..) $q->where('id', function ($q) { $q->from('actions as sub') ->selectRaw('max(id)') ->whereRaw('actions.user_id = sub.user_id'); })->where('id_action', 1); })->with('latestAction')->get(); 

Выбирайте одно из этих решений, сравнивая производительность – первый возвращает все строки и фильтрует, возможно, большую коллекцию .

Последний будет запускать подзапрос ( whereHas ) с вложенным подзапросом ( where('id', function () {..} ) , поэтому оба пути могут быть потенциально медленными на большой таблице.

Я думаю, что решение, о котором вы просите, объясняется здесь http://softonsofa.com/tweaking-eloquent-relations-how-to-get-latest-related-model/

Определите это отношение в модели пользователя,

 public function latestAction() { return $this->hasOne('Action')->latest(); } 

И получить результаты с помощью

 User::with('latestAction')->get(); 

Давайте немного изменим код @ berkayk.

Определите это отношение в модели Users ,

 public function latestAction() { return $this->hasOne('Action')->latest(); } 

А также

 Users::with(['latestAction' => function ($query) { $query->where('id_action', 1); }])->get(); 

Laravel Использует функцию take () not Limit

Попробуйте приведенный ниже код. Надеюсь, он отлично работает для u

 Users::with(['action' => function ($query) { $query->orderBy('created_at', 'desc')->take(1); }])->get(); 

или просто добавьте метод принятия к вашим отношениям, как показано ниже.

  return $this->hasMany('Action', 'user_id')->orderBy('created_at', 'desc')->take(1);