在 Laravel 5.5 中使用 Typeahead.js 使用两个表格列进行自动完成搜索

Posted

技术标签:

【中文标题】在 Laravel 5.5 中使用 Typeahead.js 使用两个表格列进行自动完成搜索【英文标题】:Autocomplete Search in Laravel 5.5 with Typeahead.js using two table columns 【发布时间】:2019-08-30 20:43:01 【问题描述】:

我有一个如下所示的数据库:

-------------------------------------
| id | FirstName | LastName | Email |
-------------------------------------
|  1 |    Test   | Customer | null  |
|  2 |    Some   |   Name   | null  |
-------------------------------------

现在我想要的是通过匹配 FirstName 和 LastName 来获取客户的 id...如果它们是在一行中找到的,那么就去获取 id。

我使用的是 Laravel 5.5.28,我尝试了 Typeahead.js 以实现我最初想要的,但由于某种原因,我只能使其与 FirstName 或 LastName 的一列一起使用。

这是工作代码(仅适用于名字):

CDN

  <script src=" asset('js/vendor/jquery.min.js') "></script>
  <script src=" asset('js/vendor/popper.min.js') "></script>
  <script src=" asset('js/vendor/bootstrap.min.js') "></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-3-typeahead/4.0.1/bootstrap3-typeahead.min.js"></script>

SearchController.php

public function autocomplete(Request $request)
    
        $datas = Customers::select("FirstName")
                 ->where("FirstName", "LIKE","%$request->input('query')%")
                 ->get();

        $dataModified = array();
        foreach ($datas as $data)
        
            $dataModified[] = $data->FirstName;
        

        return response()->json($dataModified);
    

在“JobsController.php”中获取id

public function store(Request $request)
    
        $job =  new Jobs;
        $job->cust_id = Customers::where('FirstName', $request->input('customer_name'))->value('id');

        dump($job->cust_id);
    

这是风景:

!! Form::open(['action' => 'JobsController@store', 'method' => 'POST']) !!

Form::text('customer_name', '', ['class' => 'form-control typeahead', 'placeholder' => 'Type in customer name...'])
Form::submit('Create Job', ['class' => 'btn btn-primary mt-2'])

!! Form::close() !!

路线

Route::get('jobs.create', 'SearchController@index')->name('search');
Route::get('autocomplete', 'SearchController@autocomplete')->name('autocomplete');

jQuery

<script type="text/javascript">
     var path = " route('autocomplete') ";
       $('input.typeahead').typeahead(
         source: function(query, process) 
         return $.get(path,  query: query , function(data) 
         return process(data);
        );
           
            );
</script>

现在这工作得很好,但只适用于名字。我想要的是让它适用于全名(FirstName + LastName)

我设法使它与 FirstName 和 LastName 一起工作,但只是在“前端”......它没有从数据库中获取 id。

为了在自动完成建议中同时包含 FirstName 和 LastName(开始输入时),我做了以下操作:

SearchController.php

public function autocomplete(Request $request)
    
        $datas = Customers::select("FirstName", "LastName")
                 ->where("FirstName", "LIKE","%$request->input('query')%")
                 ->get();

        $dataModified = array();
        foreach ($datas as $data)
        
            $dataModified[] = $data->FirstName .' '. $data->LastName;
        

        return response()->json($dataModified);
    

在输入时它同时显示名字和姓氏,但它返回一个空的“id”。

我希望能够在我的查询中同时使用 FirstName 和 LastName 列,因此只有在 FirstName 和 LastName 匹配时才能获得 id。

期待你的想法。

感谢您的宝贵时间。真的很感激。

更新 #1


与此同时,我已经更改了 SearchController 中的查询,所以我认为这里的代码现在可以了:

$datas = Customers::select("FirstName", "LastName")
                    ->where(function($q) use($request) 
                        $q->where("FirstName", "LIKE","%$request->input('query')%")
                          ->orWhere("LastName", "LIKE","%$request->input('query')%");
                    )->get();

唯一的问题是我仍然得到“null” id。

可能是因为我试图获取 id 的方式?

JobsController 我有这样的“存储”方法:

public function store(Request $request)
    
        $job =  new Jobs;
        $job->cust_id = Customers::where('FirstName', $request->input('customer_name'))
                                    ->orWhere('LastName', $request->input('customer_name'))
                                    ->value('id');

    

这是获取ID的正确方法吗?

更新 #2


我担心 $request->input 没有返回正确的格式,因此我在查询中得到一个“空”id 但我错了,因为一个简单的 dump();表明 $request->input 正在返回预期的字符串。

我真的没有想法了。也许我应该使用不同的方式来获取 id ?喜欢在 url 中使用 id 吗?

非常感谢任何想法和建议。谢谢。

【问题讨论】:

【参考方案1】:

我使用下面的代码工作正常

我的控制器功能

public function Search(Request $request)

    $data = Account::Join('groups','groups.group_id','=','accounts.group_id')->select("accounts.name","accounts.account_id","groups.group_name")
            ->where("name","LIKE","%".Input::get('query')."%")
            ->get()->toArray();

    return response()->json($data);

我的推特提前输入

var data = new Bloodhound(
          datumTokenizer: Bloodhound.tokenizers.obj.whitespace('value'),
          queryTokenizer: Bloodhound.tokenizers.whitespace,
          prefetch: "route('accounts/search')",
          remote: 
            url: "url('accounts/search')?query=%query",
            transform: function(list) 
                    return $.map(list, function(k,v)  return  id: k.account_id, name: k.name,group:k.group_name ; );
                ,
            wildcard: '%query'
          
        );

        $('.typeahead').typeahead(null, 
            hint: true,
            limit:100,
            highlight: true,
            minLength: 1,
            name: 'Accounts',
            displayKey: function(k) 
               return k.name + " - ("+k.group+")";
            ,
              source: data,
              templates: 
                empty: [
                  '<div class="empty-message">',
                    '<span><strong>Account Not Found</strong></span><br/>',
                    '<button type="button" class="btn btn-info" id="account_modal">+ Add New Account</button>',
                  '</div>'
                ].join('\n'),
              
        ).on('typeahead:selected', function (e, suggestion, name) 
            $(this).parent().next().val(suggestion.id);
            $(this).parent().next().next().remove();
        );

【讨论】:

您使用不同的查询结构。我认为我的比你的更简单,但由于某种原因仍然无法工作......【参考方案2】:

所以我终于解决了这个问题。我必须 CONCAT "FirstName" 和 "LastName" 才能获得 id,因为没有 CONCAT,我的代码会将 $request->input 与两列(FirstName、LastName)进行比较,并且永远不会匹配。

JobsController 中的工作查询:

$field = DB::raw("CONCAT(`FirstName`, ' ', `LastName`)");
$query = $request->input('custName');

$job =  new Jobs;
$job->cust_id = Customers::where($field, "LIKE", "%$query%")->value('id');

感谢大家的宝贵时间。真的很感激。

【讨论】:

以上是关于在 Laravel 5.5 中使用 Typeahead.js 使用两个表格列进行自动完成搜索的主要内容,如果未能解决你的问题,请参考以下文章

Laravel 5.5 中的多字段排序

作曲家自动加载 Laravel 5.5

如何在 Laravel 框架中降级? (5.6 至 5.5)

无法在 Laravel 5.5 中使用 axios 获取记录

如何在 laravel 5.5 中使用 phpunit 测试中间件?

无法使用 laravel 5.5 建立 laravel 关系