Как ограничить количество строк для определенного значения внешнего ключа в Laravel

У нас есть таблица сообщений, а user_id — это внешний ключ. Например, я хочу выбрать посты для этих пользователей

$users=[1,2,13,16,17,19];
$posts = Post::whereIn('user_id', $users)->paginate(10);

Но я хочу, чтобы у пользователя 1 и 2 было только два сообщения в выводе, для остальных пользователей количество сообщений не ограничено.

Note: User 1 and 2 are not always within the $users array, and due to the condition, one or both of them may not be in the array.

У вас есть решение для меня?

Пользователь 1 и пользователь 2 будут иметь по 2 сообщения каждый или они будут иметь два сообщения вместе?

Mozammil 23.01.2019 10:04

Всегда ли 1 и 2 должны быть ограничены двумя постами? а какие два поста первые два поста или последние два поста?

Rehan 23.01.2019 10:04

@Mozammil Пользователь 1 Два сообщения и пользователь 2 Всего два сообщения 4 сообщения

Vajiheh Habibi 23.01.2019 10:06

@Rehan Да, это всегда 1 и 2, и нужно выбрать два последних сообщения этих пользователей.

Vajiheh Habibi 23.01.2019 10:08

Что вы пробовали? Покажи нам свой код. SO не является службой написания кода.

Don't Panic 23.01.2019 10:09

@Don'tPanic Я хотел использовать союз, но поскольку он использовался для другого результата, я пытаюсь найти лучшее решение.

Vajiheh Habibi 23.01.2019 10:17

Покажи нам свой код. Посетите справочный центр и прочтите как спросить и как создать минимальный, полный и проверяемый пример.

Don't Panic 23.01.2019 10:25

@Don'tPanic Спасибо, я проверю еще раз

Vajiheh Habibi 23.01.2019 10:44
Освоение архитектуры микросервисов с Laravel: Лучшие практики, преимущества и советы для разработчиков
Освоение архитектуры микросервисов с Laravel: Лучшие практики, преимущества и советы для разработчиков
В последние годы архитектура микросервисов приобрела популярность как способ построения масштабируемых и гибких приложений. Laravel , популярный PHP...
Как построить CRUD-приложение в Laravel
Как построить CRUD-приложение в Laravel
Laravel - это популярный PHP-фреймворк, который позволяет быстро и легко создавать веб-приложения. Одной из наиболее распространенных задач в...
Освоение PHP и управление базами данных: Создание собственной СУБД - часть II
Освоение PHP и управление базами данных: Создание собственной СУБД - часть II
В предыдущем посте мы создали функциональность вставки и чтения для нашей динамической СУБД. В этом посте мы собираемся реализовать функции обновления...
Документирование API с помощью Swagger на Springboot
Документирование API с помощью Swagger на Springboot
В предыдущей статье мы уже узнали, как создать Rest API с помощью Springboot и MySql .
Роли и разрешения пользователей без пакета Laravel 9
Роли и разрешения пользователей без пакета Laravel 9
Этот пост изначально был опубликован на techsolutionstuff.com .
Как установить LAMP Stack - Security 5/5 на виртуальную машину Azure Linux VM
Как установить LAMP Stack - Security 5/5 на виртуальную машину Azure Linux VM
В предыдущей статье мы завершили установку базы данных, для тех, кто не знает.
0
8
229
5
Перейти к ответу Данный вопрос помечен как решенный

Ответы 5

Вы можете сделать это с помощью ->take()

$posts = [];
$users=[1,2,13,16,17,19];

foreach($users as $user)
{
    if ($user == 1 || $user == 2)
    {
        $posts[] = Post::where('user_id', $user)->take(2)->get();
    }
    else
    {
       $posts[] = Post::where('user_id', $user)->get();
    }
}

Подробнее читайте на https://laravel.com/docs/5.7/queries

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

Rehan 23.01.2019 10:06

В этом ответе вы можете отфильтровать, сколько постов вы хотите получить для user 1 и user 2, используя ->take(), а остальные займут все посты.

MONSTEEEER 23.01.2019 10:07

@ Рехан, о, я вижу? но могу я спросить, почему?

MONSTEEEER 23.01.2019 10:07

Даже если это потребуется, запросы выполняются в цикле, которого следует избегать.

Rehan 23.01.2019 10:08

Предположим, у вас есть 100 тыс. строк, запросы должны выполняться 100 тыс. раз и влиять на производительность приложения.

Rehan 23.01.2019 10:08

Рекомендуется извлекать данные в одном запросе, а затем изменять их с помощью цикла.

Rehan 23.01.2019 10:11

Проверьте мой ответ для решения.

Rehan 23.01.2019 10:22
Ответ принят как подходящий

Вы можете попробовать эту альтернативу:

$posts = [];
$users=[1,2,13,16,17,19];
$userWithJustTwo = [1,2];
$result = array_intersect($users, $userWithJustTwo); 
$posts[] = Post::whereIn('user_id', $result)->orderBy('created_at', 'desc')->take(2)->get();
$array = array_diff($users, userWithJustTwo);
$posts[] = Post::whereIn('user_id', $array)->get();

Это мы не получаем последние два сообщения, так как OP запросил пользователя [1,2]

Rehan 23.01.2019 10:20

@Maraboc Спасибо, позвольте мне проверить это

Vajiheh Habibi 23.01.2019 10:31

Вы не можете добиться этого в одном запросе, нам нужно взять его отдельно, как это

$users=[1,2,13,16,17,19];
// first take all the post except the two
$posts = Post::whereIn('user_id', $users)->whereNotIn('user_id', [1,2])->get()->toArray();
// then take one user 1 post in desc and limit it by 2
$userOnePost = Post::whereIn('user_id', $users)->where('user_id', 1)->limit(2)->orderBy('post.id', 'desc')->get()->toArray();
// then take one user 2 post in desc and limit it by 2
$userTwoPost = Post::whereIn('user_id', $users)->where('user_id', 2)->limit(2)->orderBy('post.id', 'desc')->get()->toArray();

// merge all the array
$allPost = array_merge(posts,$userOnePost,userTwoPost);

Проверьте это и дайте мне знать, было ли это полезно @Vajiheh habibi

Rehan 23.01.2019 10:21

Спасибо, позвольте мне проверить это

Vajiheh Habibi 23.01.2019 10:30

попробуйте этот метод:

$users = User::whereNotIn('id', [1,2])->pluck('id');
$posts = [];

$posts[] = Post::whereIn('user_id', [1,2])->take(2)->get();
$posts[] = Post::whereIn('user_id', $users)->get();

если вы хотите получить последнюю версию post, используйте это:

$posts[] = Post::whereIn('user_id', [1,2])->latest('created_at')->take(2)->get();

вы также можете использовать группировку параметров, как это

DB::table('post')
            ->whereIn('user_id', $users)
            ->where(function ($query) {
                $query->whereIn('user_id', [1,2])->limit(2)
                      ->orWhereNotIn('user_id', [1,2]);
            })
            ->get();

Другие вопросы по теме