binggle's avatar

How to use orderBy in with ?

I have this query.

$menus =  Menu::query()
    ->with(['post_cats' => function($query) {
        $query->where('status', PostCatStatusEnum::ACTIVE)
            ->orderBy('show_order', 'asc');
    }])
    ->with('post_cats.menu')
    ->find(6);

this give me this results , which is not what I exprect.

Illuminate\Support\Collection^ {#2429
  #items: array:5 [
    15 => 1
    16 => 3
    22 => 2
  ]
  #escapeWhenCastingToString: false
} 

What I exptedted is this.

Illuminate\Support\Collection^ {#2429
  #items: array:5 [
    15 => 1
    22 => 2
    16 => 3
  ]
  #escapeWhenCastingToString: false
}

How should I use OrderBy in with ?

0 likes
3 replies
jaseofspades88's avatar

For a start, passing an integer to find() will only ever return one model instance. In your example $menus is either going to be an instance of a model with the id of 6 or it will be null.

Based on this we can further conclude you're not ordering anything. If you with to return the post_cats ordered by show_order then you can try the following...

$categories = Menu::find(6)->post_cats()->orderBy('show_order')->get();

There are, however better ways to do this... you could put the ->orderBy() on the relationship..

I would recommend naming things better too for future reference... postCategories reads better than post_cats, for example...

binggle's avatar

@Snapey Thanks for reply..

Each Menu and PostCat model has 'show_order' field.

Actually my function is this.

function get_menus() {
    return Menu::query()
        ->with( ['post_cats'=>function( $query){
            $query->where('status', PostCatStatusEnum::ACTIVE)
                ->orderBy('show_order');
        }])
        ->orderBy('show_order')
        ->get();
}

I simplified my case to make it easy.

I wonder if this is a bug of laravel .

It should be working.

Now, I am going around with editing Menu Model.

class Menu extends Model
{
    public function post_cats()
    {
        return $this->hasMany(PostCat::class)->orderBy('show_order');
    }
}

function get_menus() {
    return Menu::query()
        ->with( ['post_cats'=>function( $query){
            $query->where('status', PostCatStatusEnum::ACTIVE);
        }])
        ->orderBy('show_order')
        ->get();
}

I still wonder why 'orderBy' in side 'with' is not working.

And thanks for commenting about naming.

jaseofspades88's avatar

Maybe the with function and function scopes don't stack... have you considered adding the following to Menu model?

public function activePostCategories()
{
	return $this->hasMany(PostCat::class)
		->orderBy('show_order')
		->where('status', PostCatStatusEnum::ACTIVE);
}

...whilst here, perhaps use PostCatStatusEnum::ACTIVE->value (notice ->value) as the enum is not stored on the database and you need to check against the actual value in your enum and not the enum itself (unless casting).

Doing the above means you can simply call...

Menu::query()
	->with('activePostCategories')
	etc

Oh, also... I'd love to have the accolade of being @snapey, alas.. tis not I.

Please or to participate in this conversation.