Search code examples
phplaravelmethod-chaining

Pass chain function as paramter as parameter in php


I have a function. It has method chaining that needs to be performed.

public function someFunction()
{
        $query=$this->model;
    $query->select($columns)
        ->skip($request->get('start') * $request->get('length'))
        ->take($request->get('length'))
        ->orderBy(
            $request->get('sort_column'),
            $request->get('sort_direction')
        )
        ->get();

    //Some other task      
}

It was working fine but I need a slight modification in that function what I want is I want to pass a join in that function for method chaining.

public function someFunction($join_as_parameter)
{
        $query=$this->model;
    $query->select($columns)
        //Join should be executed here as a parameter in method chaning . 
        ->skip($request->get('start') * $request->get('length'))
        ->take($request->get('length'))
        ->orderBy(
            $request->get('sort_column'),
            $request->get('sort_direction')
        )
        ->get();

    //Some other task      
}

So that final function execution will be like this

public function someFunction($join_as_parameter)
{
        $query=$this->model;
    $query->select($columns)
        ->join('table','sometable.id', '=', 'other_table') 
        ->skip($request->get('start') * $request->get('length'))
        ->take($request->get('length'))
        ->orderBy(
             $request->get('sort_column'),
             $request->get('sort_direction')
        )
        ->get();

    //Some other task      
}

Is there any way to do this? Any help would be appreciated. Thanks.


Solution

  • This way you can achieve what you need.

    use DB;
    use Closure;
    use Illuminate\Database\Query\JoinClause;
    
    public function someFunction(Closure $join_clauser)
    {
        //create Query Builder object
        $query = DB::query();
    
        //Add the `$join` object to the table joins for this query
        $join_as_parameter = call_user_func($join_closure, $query);
        $query->joins = array_merge((array) $query->joins, [$join_as_parameter]);
    
        $query->select($columns)
            ->skip($request->get('start') * $request->get('length'))
            ->take($request->get('length'))
            ->orderBy(
                $request->get('sort_column'),
                $request->get('sort_direction')
            )
            ->get();
    
        //Some other task
    }
    
    //create Query Builder object
    $query = DB::query();
    

    And execute the functions as,

    someFunction(function($query){
        // return JoinClause object with joining conditions
        return (new JoinClause($query, 'inner', 'table'))
                ->on('table.id', '=', 'othe_table.table_id');
    });
    

    Furthermore, you can modify this to pass array of joins to add multiple joins your the query.

    To use this with eloquent models, replace

    $query = DB::query();
    

    with

    $query = Model::query()->getQuery();
    

    NOTE : ->getQuery() is used to retrieve the Query\Builder object since JoinClause expects it as the first param.