Search code examples
laraveleloquent

How to reuse parts of Eloquent builder in Laravel


Is there a way to reuse parts of a query in Laravel? For example if I have two queries which share some arbitrarily long section, can I create a function/variable that can be used in place of that section?

Toy queries:

$a = TableA::join('tableb', 'tablea.bid', '=', tableb.id)
           ->join('talbec', 'tableb.cid', '=', tablec.id)
           ->join('tabled', 'tablec.did', '=', tabled.id)
           ->where('tablea_col', '=', true)->get();

$b = TableA::join('tableb', 'tablea.bid', '=', tableb.id)
           ->join('talbec', 'tableb.cid', '=', tablec.id)
           ->join('tabled', 'tablec.did', '=', tabled.id)
           ->where('tableb_col', '=', true)->get();

I would like something like:

$shared = TableA::join('tableb', 'tablea.bid', '=', tableb.id)
           ->join('talbec', 'tableb.cid', '=', tablec.id)
           ->join('tabled', 'tablec.did', '=', tabled.id);

$a = shared->where('tablea_col', '=', true)->get();

$b = shared->where('tableb_col', '=', true)->get();

Solution

  • From Laravel 8+, you can clone it then reuse as you wish:

    $shared = TableA::join('tableb', 'tablea.bid', '=', tableb.id)
               ->join('talbec', 'tableb.cid', '=', tablec.id)
               ->join('tabled', 'tablec.did', '=', tabled.id);
    
    $a = $shared->clone()->where('tablea_col', true)->get();
    
    $b = $shared->clone()->where('tableb_col', true)->get();
    

    before Laravel 8, use

    $a = clone $shared;
    $b = clone $shared;
    $a = $a->where('tablea_col', true)->get();
    $b = $b->where('tableb_col', true)->get();