I have created filters to search based on the input. For example, if the request has 'number', it uses the Number class, which implements Filter.
The second thing I have is a search where the response is returned through a JsonResource. I'm using this in a Vue component.
I want to combine the two. Where inside of the filter do I implement the JsonResource?
namespace App\OrderSearch;
use App\Models\Order\Order;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Http\Request;
class OrderSearch
{
public static function apply(Request $filters)
{
$query = static::applyDecoratorsFromRequest($filters, (new Order())->newQuery());
return static::getResults($query);
}
private static function applyDecoratorsFromRequest(Request $request, Builder $query)
{
foreach ($request->all() as $filterName => $value) {
$decorator = static::createFilterDecorator($filterName);
if (static::isValidDecorator($decorator)) {
$query = $decorator::apply($query, $value);
}
}
return $query;
}
private static function createFilterDecorator($name)
{
return __NAMESPACE__ . '\Filters\' . ucfirst($name);
}
private static function isValidDecorator($decorator)
{
return class_exists($decorator);
}
private static function getResults(Builder $query)
{
return $query->get();
}
}
namespace App\Http\Controllers\Order;
use App\Http\Controllers\Controller;
use App\Http\Resources\OrderResource;
use App\Models\Order\Order;
use App\OrderSearch\OrderSearch;
use Illuminate\Http\Request;
use Illuminate\Support\Carbon;
class SearchController extends Controller
{
protected $order;
public function __construct(Order $order)
{
$this->order = $order;
}
public function filter(Request $request)
{
return OrderSearch::apply($request);
}
}
namespace App\OrderSearch\Filters;
use Illuminate\Database\Eloquent\Builder;
interface Filter
{
/**
* @param Builder $builder
* @param $value
* @return mixed
*/
public static function apply(Builder $builder, $value);
}
namespace App\OrderSearch\Filters;
use Illuminate\Database\Eloquent\Builder;
class Number implements Filter
{
public static function apply(Builder $builder, $value)
{
return $builder->where('number', 'LIKE', '%' . $value . '%');
}
}
use Illuminate\Http\Resources\Json\JsonResource;
use Illuminate\Support\Carbon;
class OrderResource extends JsonResource
{
/**
* Transform the resource into an array.
*
* @param \Illuminate\Http\Request $request
* @return array
*/
public function toArray($request)
{
return [
'number' => $this->number,
'requested_ship_date' => Carbon::parse($this->requested_ship_date)->format('m-d-Y'),
'status' => $this->status,
];
}
}