繁体   English   中英

如何仅在 Laravel 中获得一个搜索查询过滤器的结果

[英]How can I get results of one search query filter only in Laravel

我正在创建一个房地产项目,该项目将为具有不同搜索过滤器的不同页面提供搜索选项。

这是搜索视图的一个示例

<form class="form-row basic-select-wrapper" method="POST" action="{{route('filter')}}">
    @csrf
    {{-- <div class="form-group">
        <input type="text" name="prop_name">
    </div> --}}
    <div class="form-group col-lg col-md-6">
        <label>Property type</label>
        <select name="type_id" class="form-control basic-select">
            <option>Select Type</option>
            @foreach ($types as $type)
            @if ($type->status == 1)
                <option value="{{ $type->id }}">{{ $type->name }}</option>
            @endif
            @endforeach
        </select>
    </div>
    <div class="form-group col-lg col-md-6">
        <label>Property Category</label>
        <select name="cat_id" class="form-control basic-select">
            <option>Select Category</option>
            @foreach ($categories as $category)
                <option value="{{ $category->id }}">{{ $category->name }}</option>
            @endforeach
        </select>
    </div>
    <div class="form-group col-lg col-md-6">
        <label>Location</label>
        <select name="loc_id" class="form-control basic-select">
            <option>Select Location</option>
            @foreach ($locations as $location)
                <option value="{{ $location->id }}">{{ $location->loc_name }}</option>
            @endforeach
        </select>
    </div>

    <div class="form-group col-lg col-md-6">
        <label>Budget</label>
        <select name="start_price" class="form-control basic-select">
            <option>Select Budget</option>
            @foreach($price['price'] as $key => $val)
                <option value="{{$key}}">{{$val}}</option>
            @endforeach
        </select>
    </div>
    <div class="form-group col-lg col-md-6">
        <label>Bedroom(s)</label>
        <select name="min_bed" class="form-control basic-select">
            <option>Select Bedroom</option>
                <option value="0">studio</option>
                <option value="1">one bedroom</option>
                <option value="2">two bedroom</option>
                <option value="3">three bedroom</option>
                <option value="4">four bedroom</option>
                <option value="5">five bedroom</option>
                <option value="6">six bedroom</option>
                <option value="7">seven bedroom</option>
        </select>
    </div>
    <div class="advanced-search" id="advanced-search">
        <div class="card card-body">
            <div class="form-group col-md-12">
                <div class="mt-0">
                    <button class="btn btn-primary align-items-center" type="submit"><i
                            class="fas fa-search mr-1"></i><span>Search</span></button>
                </div>
            </div>
        </div>
    </div>
</form>

这是我的搜索 controller

 <?php

namespace App\Http\Controllers\User;

use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
//use App\Models\Listing;
use App\ListingSearch\ListingSearch;

class SearchController extends Controller
{
    public function filter(Request $request)
    {
        return ListingSearch::apply($request);
    }

}

现在,要实现这一点,因为有多个搜索过滤器,我想简化它。 这里是文件夹结构文件夹结构

这是列表搜索 Class

<?php

namespace App\ListingSearch;

use Illuminate\Database\Eloquent\Builder;

use App\Models\Listing;
use Illuminate\Http\Request;

class ListingSearch
{
    public static function apply(Request $filters)
    {
        $query = static::applyDecoratorsFromRequest(
                $filters, (new Listing)->newQuery()
            );
        // Get the results and return them.
        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\\' .
            str_replace(' ', '',
                ucwords(str_replace('_', ' ', $name)));
    }

    private static function isValidDecorator($decorator)
    {
        return class_exists($decorator);
    }

    private static function getResults(Builder $query)
    {
        return $query->get();
    }
}

这是类别的过滤器 CATID 之一的示例

<?php

namespace App\ListingSearch\Filters;

use Illuminate\Database\Eloquent\Builder;

class CatId implements Filter
{
    public static function apply($builder, $value)
    {
        return $builder->where('cat_id', $value);
    }
}

这样做的问题是我必须输入所有必需的过滤器才能获得结果,否则如果我只填写一个过滤器,我会得到 null 结果,例如我只想要公寓,而不输入位置或类别。 我怎样才能做到这一点?

搜索查询

您是否尝试在将 $value 堆叠到您的位置之前对其进行过滤?

    if (!empty($value)) {

    }

empty() 将负责过滤掉空值和 null 值。 因此,您最终会添加实际存在的查询过滤器值。

编辑

    foreach ($request->all() as $filterName => $value) {

        if (!empty($value)) {
            $decorator = static::createFilterDecorator($filterName);

            if (static::isValidDecorator($decorator)) {
                $query = $decorator::apply($query, $value);
            }
        }
    }

编辑 2

您的选项标签没有定义值属性,并且在发布到 controller 时它不为空,因为浏览器默认为标签内的值(选择类型,Select 类别等)。 您需要将 value 属性提供为空,以便 POST 不使用这样的内部文本:

<option value="">Select Type</option>
[...]
<option value="">Select Category</option>
[...]
<option value="">Select Location</option>
[...]
<option value="">Select Budget</option>

然后 if (!empty($value)) {} 可以做到这一点

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM