ashok poudel
ashok poudel

Reputation: 723

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.

Upvotes: 3

Views: 390

Answers (1)

Ijas Ameenudeen
Ijas Ameenudeen

Reputation: 9259

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.

Upvotes: 2

Related Questions