6

I got stuck here been trying from 2-3 hours.

I have a many to many relation:

class Category extends Model
{
    public function news()
    {
        return $this->belongsToMany('App\News');
    }
}  

class News extends Model
{
    public function categories()
    {
        return $this->belongsToMany('App\Category');
    }
}

I am trying to get latest 5 news of the related categories:

$front_categories = Category::with(array(
        'news'=>function($query){
        $query->where('publish','1')->orderBy('created_at', 'desc')->take(5);}))
       ->where('in_front', 1)->get();

The above query is not working for me it give a total of five results instead of 5 result for each categories.

Mihkel Allorg
  • 929
  • 1
  • 8
  • 26
sanu
  • 1,048
  • 3
  • 14
  • 28

2 Answers2

1

Based on what I know about Laravel, you could try doing it this way instead.

class Category {

    public function recentNews()
    {
        return $this->news()->orderBy('created_by', 'DESC')
                            ->take(5);
    }
}

// Get your categories
$front_categories = Category::where('in_front', 1)->get();

// load the recent news for each category, this will be lazy loaded
// inside any loop that it's used in.
foreach ($front_categories as $category) {
    $category->recentNews;
}

This has the same effect as Lê Trần Tiến Trung's answer and results in multiple queries. It also depends on if you're reusing this functionality or not. If it is a one-off, it may be better to put this somewhere else. Other ways could also be more dynamic, such as creating a method that returns the collection of categories and you can ask it for a certain number:

class CategoriesRepository {

    public static function getFrontCategories(array $opts = []) {

        $categories = Category::where('in_front', 1)->get();

        if (!empty($opts) && isset($opts['withNewsCount'])) 
        {
            foreach ($categories as $category) 
            {
                $category->recentNews = static::getRecentNewsForCategory(
                    $category->id,
                    $opts['withNewsCount']
                );
            }
        }

        return $categories;
    }
}

$front_categories = CategoriesRepository::getFrontCategories([
    'withNewsCount' => 5
]);
jardis
  • 687
  • 1
  • 8
  • 16
0

I think, Because you do eager loading a collection which has more than one record.

To solve it, you need to loop

$front_categories = Category::where('in_front', 1)->get();

foreach ($front_categories as $fCategory) {
    $fCategory->load(['news' => function($query) {
        $query->where('publish','1')->orderBy('created_at', 'desc')->take(5);
    }]);
}

This solution will do many queries to DB. If you want to do with only 1 query, checkout this Using LIMIT within GROUP BY to get N results per group?

Community
  • 1
  • 1
Trung
  • 650
  • 1
  • 5
  • 15
  • what i did is $front_categories = Category::where('in_front', 1)->orderBy('position', 'asc')->get(); in my category model public function newsTop5() { return $this->news()->orderBy('created_at', 'desc')->take(5); } and in my blade @foreach($front_category->newsTop5 as $news) – sanu Sep 11 '15 at 17:44