【问题标题】:How can I get results of one search query filter only in Laravel如何仅在 Laravel 中获取一个搜索查询过滤器的结果
【发布时间】:2021-05-17 02:15:10
【问题描述】:

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

这是搜索视图的一个示例

<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>

这是我的搜索控制器

 <?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);
    }

}

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

这是Listitng搜索类

<?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);
    }
}

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

search query

【问题讨论】:

    标签: php mysql laravel


    【解决方案1】:

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

        if (!empty($value)) {
    
        }
    

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

    编辑

        foreach ($request->all() as $filterName => $value) {
    
            if (!empty($value)) {
                $decorator = static::createFilterDecorator($filterName);
    
                if (static::isValidDecorator($decorator)) {
                    $query = $decorator::apply($query, $value);
                }
            }
        }
    

    编辑 2

    您的选项标签没有定义值属性,并且当发布到您的控制器时它不为空,因为浏览器默认为标签内的值(选择类型,选择类别等)。您需要将 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)) {} 就可以了

    【讨论】:

    • 如果我输入3个过滤器,即位置、类型和类别,我得到过滤查询的结果。如果我只输入没有类型和类别的位置,则不会显示任何结果@Patrick
    • 请看我的编辑...在我看来你没有过滤掉空值。
    • 即使添加了编辑,它仍然没有过滤三个@Patrick 中的一个查询
    • 你能分享一下它传递给 MySQL 的实际查询吗?此外,您可能想转储 $request->all() 并查看里面有什么。查看浏览器控制台中的 POST 标头以查看空请求的值。它可能不是 NULL 或空的。
    • 当我考虑到 3 个查询、位置、类型和类别时,我得到了过滤值的结果。当我只考虑一个因素时,比如位置,当我 dd($request) 我得到 [ ] @patrick
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-05-14
    • 1970-01-01
    • 2019-04-17
    • 1970-01-01
    • 2015-11-24
    • 2013-02-04
    • 2019-08-13
    相关资源
    最近更新 更多