1

I have a Laravel project with Categories and Children - I've got this function in my model:

    public static function tree() {
        return Category::with(implode('.', array_fill(0, 100, 'children')))->where('parent_id', '=', NULL)->get();
    }

Which I then call with $categories = Category::tree();

And on the view I have:

@foreach($categories as $index => $category)
   {{ $category->title }}
   @foreach($category['children'] as $child)
      {{ $child->title }}
   @endforeach
@endforeach

That works fine - but I'm trying to sort the children alphabetically now.

I've tried this:

public static function tree() {
        return Category::with([implode('.', array_fill(0, 100, 'children')) => function($query) {
            $query->orderBy('title', 'ASC');
        }])->where('parent_id', '=', NULL)->get();

    }

I've also tried return Category::with(implode('.', array_fill(0, 100, 'children')))->where('parent_id', '=', NULL)->orderBy('title)->get(); but that just orders to parent categories.

But it doesn't sort them. Anyone got any ideas?

Thanks.

--EDIT--

Following Tim's suggestion on a better way, I now have:

    public function children() {

        return $this->hasMany('App\Category', 'parent_id', 'id');

    }  
    
    public function childrenCategories()
    {
        return $this->children()->with('childrenCategories');
    }

Then...

       $categories =  Category::with(['childrenCategories' => 
            function($query) {
                $query->orderBy('title', 'ASC');
            }])->where('parent_id', '=', NULL)->get();

Which works, but not the ordering part. Any suggestions?

peter88uk
  • 297
  • 1
  • 5
  • 22
  • 2
    Oh my... does this do what I think it does? `with(implode('.', array_fill(0, 100, 'children')))` equates to `children.children.children.children.children. ...` Cause if so, that's a very... odd approach to infinite depth recursive relationships. – Tim Lewis Aug 19 '20 at 15:31
  • I picked up the code a while back to be honest and it worked at the time but we're coming around to updating. I have been looking at some Laravel packages like https://github.com/lazychaser/laravel-nestedset which may be a better solution – peter88uk Aug 19 '20 at 15:35
  • 1
    Haha yeah, I understand the legacy code acquisition reasoning :P For reference, the approach I use to recursive relationships is from this answer: https://stackoverflow.com/a/26654139/3965631. Basically, a single call to `Model::with('allChildren')` will, when setup properly, load all relationship depths. It _should_ allow for properly sorting on child models too (which is the core of your question; this was just a rather long tangent on approach) – Tim Lewis Aug 19 '20 at 15:36
  • 1
    Thanks Tim. I'll take a look. – peter88uk Aug 19 '20 at 15:39
  • I've given it a go, and it works, but it's not sorting still :( Edited my post to add it on. – peter88uk Aug 19 '20 at 15:53
  • 1
    Nice :) But yeah, I think what you have wouldn't apply sorting beyond a single iteration. Something like `public function childrenSorted() { return $this->hasMany(Category::class, 'parent_id', 'id')->orderBy('title'); }`, followed by `public function childrenCategoriesSorted(){ return $this->childrenSorted()->with('childrenCategoriesSorted'); }` _should_ work. It's a little more verbose and somewhat duplicated, but might work. – Tim Lewis Aug 19 '20 at 15:57
  • Ah yes. That worked. I _may_ still look at a nesting package in the longterm but this has sorted it for now. Thank you. – peter88uk Aug 19 '20 at 21:19
  • Excellent :) And yeah, that sounds like a good idea! I looked a bit more at the `nestedset` package, and it seems like it has some pretty useful stuff in it. But glad I could help regardless. Cheers! – Tim Lewis Aug 19 '20 at 21:30

1 Answers1

0

If you don't care about performance, you can try to sort your subcollections right in the view.

@foreach($category['children']->sortBy('title') as $child)
  {{ $child->title }}
@endforeach

But it is a very, very, very bad solution!

Good way starts with reorganisstion of the whole structure of categories. I prefer nested set. There is a pretty cool implementation for Laravel. https://github.com/etrepat/baum

Roman Meyer
  • 2,634
  • 2
  • 20
  • 27
  • Thanks. It's legacy code - but I'm coming to the realisation that it probably needs to be re-worked. I've seen this- github.com/lazychaser/laravel-nestedset but I'll take a look at baum too. Thanks. – peter88uk Aug 19 '20 at 15:54