Laravel Eloquent Limit in Relation, у которого есть Sub Relation

У меня много отношений между категорией и содержанием, и мне нужно ограничение 4 содержания для каждой категории.

Я хотел бы ограничить результат отношения содержание, которое имеет подчиненное отношение к языки

Мой код

Category::with(['contents.languages' => function($query){
        $query->limit(4);
    }])
        ->get();

Но я вижу в журнале, что ограничение работает на отношении языки, а не на содержимом, которое я хотел, это ограничение на содержание

пожалуйста, уточните свой вопрос, указав более подробную информацию.

Chirag Patel 09.04.2018 13:23

Попытайтесь установить предел в своих отношениях

afsal c 09.04.2018 14:16

@ChiragPatel обновлен, надеюсь, вы понимаете

Muhamad Yulianto 09.04.2018 15:14

@afsalc У меня есть вложенное отношение content.languages, когда я устанавливаю ограничение внутри этого отношения, оно работает только с языками, а не с содержимым

Muhamad Yulianto 09.04.2018 15:15

Вы установили языковую связь, например, в классе Content Model, language function ()

afsal c 09.04.2018 15:41

@afsalc да, у функции languages ​​() есть много

Muhamad Yulianto 09.04.2018 15:44

Что насчет модели категории, которую вы поместили в отношение содержания

afsal c 09.04.2018 15:47

@afsalc да, я сделал это, в категориях много содержания, в содержании много языков

Muhamad Yulianto 09.04.2018 15:51

Не могли бы вы разместить здесь свой класс модели категории

afsal c 09.04.2018 15:53

@afsalc Я не понимаю о чем ты

Muhamad Yulianto 09.04.2018 15:54

Посмотри на тпойка ответ

afsal c 09.04.2018 15:55

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

Muhamad Yulianto 09.04.2018 15:57

И почему бы вам не попытаться исключить часть .languages из кода, который вы опубликовали: имея содержимое, вы можете получить языки вместо них, если установлена ​​связь?

Tpojka 09.04.2018 18:45
Освоение архитектуры микросервисов с 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
В предыдущей статье мы завершили установку базы данных, для тех, кто не знает.
4
13
1 974
6
Перейти к ответу Данный вопрос помечен как решенный

Ответы 6

Попробуй это

Category::with([
   'contents' => function($q) { $q->limit(4); },
   'contents.languages'
])->get();

Хотя этот код может ответить на вопрос, предоставление дополнительного контекста относительно того, почему и / или как этот код отвечает на вопрос, улучшает его долгосрочную ценность.

Maximilian Peters 09.04.2018 14:54

Не работает, ограничивает категорию, а не содержимое

Muhamad Yulianto 09.04.2018 15:16

Вы должны попробовать это:

Category::with(['contents.languages'])->limit(4)->get();

он будет ограничиваться категорией, а не содержанием

Muhamad Yulianto 09.04.2018 15:05

Этот вопрос в основном похож на Получить первые n записей для каждой группы сгруппированных результатов

Насколько я понимаю, выбора нет, кроме как выполнять N + 1 запросов. Вы можете добиться этого, выполнив:

  $categories = Category::get(); 
  $categories->each(function ($category) {
     $category->load([ 'contents' => function ($q) {
             return $q->limit(4);
     }, 'contents.languages']);
  });

Можем ли мы сделать лучше? Я сомневаюсь, что это сомнительно, хотя я открыт для идей. Хотя мы можем оптимизировать это, чтобы отправлять меньше запросов к базе данных, внутренняя база данных все равно должна будет вычислять N + 1 запросов.

не работает, содержимое просто показывает 4, у меня много отношений между категориями и содержимым, я хочу ограничить 4 содержимого для каждой категории

Muhamad Yulianto 09.04.2018 15:13

Вы имеете в виду, что в содержимом отображается просто цифра 4?

apokryfos 09.04.2018 15:15

Я имею в виду 4 элемента, у меня много категорий и много содержимого, я хочу получить все категории, но только 4 содержимого для каждой категории

Muhamad Yulianto 09.04.2018 15:17

Вы только что сказали, что хотите получить 4 содержимого для каждой категории, и вы получаете 4 содержимого для каждой категории. Что не работает?

apokryfos 09.04.2018 15:18

Он просто показывает 4 содержимого для всех категорий, а не для каждой категории. в журнале я вижу это: выберите * из content, где content.category_id в ('2', '3') limit 4

Muhamad Yulianto 09.04.2018 15:19

Я думал, что это возможно, но, вероятно, этого не произойдет с одним запросом, ожидающим загрузки. Может быть, но я не знаю как. В любом случае это обновление должно работать, но выполнит N + 1 запросов.

apokryfos 09.04.2018 15:45
Ответ принят как подходящий

Функции take () и limit () не будут работать с активной загрузкой, если вы получите более одной родительской модели с помощью get ().

Так что тебе нужно пойти другим путем,

$categories = Category::with('contents')->get();

После получения $categories вы можете выполнить цикл foreach, как показано ниже:

$contents = [];
foreach($categories as $category){
   $category->limitedContents = $category->contents()->with('languages')->limit(4);
}

И, сделав это, вы получите 4 содержимого на категорию во всех категориях с limitedContents.

Note: Here I used name as 'limitedContents' because you have already defined contents relationship.

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

Muhamad Yulianto 09.04.2018 15:31

да, это займет немного больше времени, чем жадная загрузка, но с этим мы добьемся наилучшего результата :)

Chirag Patel 09.04.2018 15:33

Мне пришлось добавить -> get () после лимита (4)

Jacob Hyde 26.03.2020 22:28

Вы можете установить дополнительный метод в модели Category и выполнить вызов с его помощью:

public function contentsTake4()  
{
    return $this->hasMany('App\Content')->limit(4);
}

Тогда вы бы назвали его в контроллере как:

Category::with('contentsTake4.products')->get();

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

Muhamad Yulianto 09.04.2018 15:52

Журнал mysql выглядит так: выберите * из содержимого, где content.category_id в ('2', '3') limit 4; он будет отображать только 4 содержимого для категорий с идентификаторами 2 и 3, что я хочу, это ограничение содержимого 4 для каждой категории (2 и 3)

Muhamad Yulianto 09.04.2018 16:00

Это тоже работает

foreach(Category::with('contents')->get() as $category)
   {
        foreach($category->contents->take(4) as $content)
        {
            $languages = $content->with('languages')->get();
            foreach($languages as $language)
             {
                //your code
             }
        }
   }

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