Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Laravel: Dependency injection and static custom method for all my models

Tags:

php

laravel

I created a helper class for searching and filtering my laravel models (method uses tntsearch and a custom scope), currently it works all right but I want to make some improvements to it, sadly it's proving difficult to achieve what I want:

What I want to improve:

1) Being able to call search method statically on all my laravel models, like this:

Model::search();

Currently I have to instantiate the class and call the method like:

 $results = $searchHelper->search($request, $filters);

2)Right now I also have to pass two arguments to constructor, in my class I try dependency injection in construct magic method but I still have to pass request and filters as arguments...

How it looks in my controller:

public function search(Request $request, QueryFilters $filters)
    {
        $search = new Search($request, $filters);


        $posts = $search->search('Post', ['postcategory', 'author', 'favorites']);

        return response()->json([
            'message' => 'Encontramos unas coincidencias',
            'posts' => $posts,
        ], 200);   
    }

My helper class:

<?php
namespace App\Helpers;


use Illuminate\Http\Request;
use App\Filters\QueryFilters;
use App\Filters\Filterable;


class Search
{

    public $request;
    public $filters;

    public function __construct(Request $request, QueryFilters $filters)
    {
        $this->request = $request;
        $this->filters = $filters;
    }

    public function search( $model, $relationships = [] )
    {
        $model = app("App\Models\".$model."); 

        $results = $model::search($this->request->input('search'), '')->get(); 

        if(!$results->isEmpty())
        {
            $ids = implode(',', $results->pluck('id')->toArray());
            $filters->merge(['whereIn' => $ids]);    
        }

        $results = $model::filter($this->filters)->with($relationships)->paginate(10);

        return $results; 
    }


}

I want to call the method like this, NO passing arguments to constructor (DI should handle that), call method STATICALLY

Appointments::search();
like image 561
gabogabans Avatar asked Nov 06 '22 11:11

gabogabans


1 Answers

You can define a Searchable trait (instead of your Search class) like this:

trait Searchable
{
    public static function search($relationships = [])
    {
        //You may use the `resolve` method to resolve a class instance.
        $request = resolve(\Illuminate\Http\Request::class);
        //or $request = request();
        $filters = resolve(\App\Filters\QueryFilters::class);

        //rename the other `search` function on your model to `doSearch` to resolve conflicts
        $results = self::doSearch($request->input('search'), '')->get();
        //or using request helper function
        //$results = self::doSearch(request('search'), '')->get(); 

        if(!$results->isEmpty())
        {
            $ids = implode(',', $results->pluck('id')->toArray());
            $filters->merge(['whereIn' => $ids]);    
        }

        $results = self::filter($filters)->with($relationships)->paginate(10);

        return $results; 
    }

}

and implement this Searchable contract on your Eloquent model:

class Appointment extends Model
{
    use Searchable;

    //...
}

now you can call:

Appointment::search();
like image 178
Hafez Divandari Avatar answered Nov 14 '22 20:11

Hafez Divandari