'laravel eloquent using when() with nested load()

Dear laravel community,

is there any way to use when() with a nested load()?

See this code:

public function getOrder($order, Request $request){
...
case 'transactions':
    //this will be loaded for all orders
    $order->load([
        'referralTransactions' => function ($query) {
            $query->withTrashed();
        },
    ])
    //when order is of currency typ0 load all these relations additionally
    ->when($order->currency_type == 0, function ($query) {
        $query->load([
            'someRelation1' => function ($query) {
                $query->withTrashed();
            },
            'someRelation2' => function ($query) {
                $query->withTrashed();
            },
        ]);
    })
    //when order is of currency 1 we load other relations additionally
    ->when($order->currency_type == 1, function ($query) {
        $query->load([
            'someOtherRelation' => function ($query) {
                $query->withTrashed();
            },
        ]);
    });
break;

Any idea how to get this work? Is this supported in general?

It says Call to undefined method Illuminate\Database\Eloquent\Builder::load()



Solution 1:[1]

First solution, use load on the $order :

public function getOrder($order, Request $request){
...
case 'transactions':
    //this will be loaded for all orders
    $order->load([
        'referralTransactions' => function ($query) {
            $query->withTrashed();
        },
    ]);
    //when order is of currency typ0 load all these relations additionally
    if($order->currency_type == 0) {
        $order->load([
            'someRelation1' => function ($query) {
                $query->withTrashed();
            },
            'someRelation2' => function ($query) {
                $query->withTrashed();
            },
        ]);
    }
    //when order is of currency 1 we load other relations additionally
    if($order->currency_type == 1) {
        $order->load([
            'someOtherRelation' => function ($query) {
                $query->withTrashed();
            },
        ]);
    }
break;

second solution, use ->with() instead :

public function getOrder($order, Request $request){
...
case 'transactions':
    //this will be loaded for all orders
    $order = $order->with([
        'referralTransactions' => function ($query) {
            $query->withTrashed();
        },
    ])
    //when order is of currency typ0 load all these relations additionally
    ->when($order->currency_type == 0, function ($query) {
        $query->with([
            'someRelation1' => function ($query) {
                $query->withTrashed();
            },
            'someRelation2' => function ($query) {
                $query->withTrashed();
            },
        ]);
    })
    //when order is of currency 1 we load other relations additionally
    ->when($order->currency_type == 1, function ($query) {
        $query->with([
            'someOtherRelation' => function ($query) {
                $query->withTrashed();
            },
        ]);
    })->first();
break;

i think the second option is better, it will make one query instead of 2

edit :

here a third solution, adapted from the first one :

public function getOrder($order, Request $request){
...
case 'transactions':
    //this will be loaded for all orders
    $load = [
        'referralTransactions' => function ($query) {
            $query->withTrashed();
        },
    ];
    
    
    //when order is of currency typ0 load all these relations additionally
    if($order->currency_type == 0) {
        $load = array_merge([
            'someRelation1' => function ($query) {
                $query->withTrashed();
            },
            'someRelation2' => function ($query) {
                $query->withTrashed();
            },
        ], $load);
    }
    //when order is of currency 1 we load other relations additionally
    if($order->currency_type == 1) {
        $load = array_merge([
            'someOtherRelation' => function ($query) {
                $query->withTrashed();
            },
        ], $load);
    }
    $order->load($load);
break;

you can do a single ->load() that way

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1