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();
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();
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With