Laravel中如何用Typeahead.js实现姓名双向匹配的自动补全搜索
Laravel + Typeahead.js: Support "Lastname Firstname" & "Firstname Lastname" Search
Hey there! Let's refine your setup to make sure your autocomplete works seamlessly for both name orders, plus your existing mobile search. Here's a step-by-step fix:
1. Improve Controller Logic
Your current code handles single-term searches well, but it misses the combined name order scenarios. Let's adjust the query to account for both "Firstname Lastname" and "Lastname Firstname" when two terms are entered:
public function autocomplete(Request $request) { $query = $request->input('query'); $searchTerms = preg_split('/\s+/', trim($query), -1, PREG_SPLIT_NO_EMPTY); $usersQuery = Profile::query(); if (count($searchTerms) === 2) { // Handle both name combinations when two terms are provided [$firstTerm, $secondTerm] = $searchTerms; $usersQuery->where(function ($q) use ($firstTerm, $secondTerm) { // Match "Firstname Lastname" $q->where('firstname', 'like', "%{$firstTerm}%") ->where('lastname', 'like', "%{$secondTerm}%") // OR match "Lastname Firstname" ->orWhere(function ($subQ) use ($firstTerm, $secondTerm) { $subQ->where('firstname', 'like', "%{$secondTerm}%") ->where('lastname', 'like', "%{$firstTerm}%"); }); }); } else { // For single terms (or more than 2), match any field as before foreach ($searchTerms as $term) { $usersQuery->where(function ($q) use ($term) { $q->orWhere('firstname', 'like', "%{$term}%") ->orWhere('lastname', 'like', "%{$term}%") ->orWhere('mobile', 'like', "%{$term}%"); }); } } // Format results to play nicely with Typeahead (include full name for display) $results = $usersQuery->get(['firstname', 'lastname', 'mobile'])->map(function ($profile) { return [ 'value' => "{$profile->firstname} {$profile->lastname}", 'firstname' => $profile->firstname, 'lastname' => $profile->lastname, 'mobile' => $profile->mobile ]; }); return response()->json($results); }
Key Changes:
- Two-term handling: We explicitly check for two search terms and use nested
where()clauses to match both name orders (prevents the OR condition from leaking into other search logic). - Result formatting: We map the database results to include a
valuefield—this is what Typeahead uses for default display, making it easy to show the full user name.
2. Frontend Typeahead.js Setup
Now let's set up the frontend to consume this endpoint. Make sure you've included jQuery and Typeahead.js first, then initialize the plugin:
<!-- Load dependencies --> <script src="https://code.jquery.com/jquery-3.7.1.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/typeahead.js/0.11.1/typeahead.bundle.min.js"></script> <!-- Your search input --> <input type="text" id="user-search" placeholder="Search by name or mobile..."> <script> $(document).ready(function() { $('#user-search').typeahead({ hint: true, highlight: true, minLength: 1 // Start searching after 1 character }, { name: 'users', source: function(query, syncResults, asyncResults) { // Fetch results from your Laravel endpoint $.ajax({ url: '/autocomplete', // Update this to match your route method: 'GET', data: { query: query }, success: function(data) { asyncResults(data); }, error: function() { asyncResults([]); // Fallback to empty if something breaks } }); }, display: 'value', // Use the full name as the default display text templates: { // Customize how suggestions look in the dropdown suggestion: function(profile) { return ` <div class="suggestion-item"> <strong>${profile.value}</strong> <br> <small>Mobile: ${profile.mobile}</small> </div> `; } } }); }); </script>
3. Route Configuration
Don't forget to add the route in routes/web.php (or routes/api.php if you're using an API route):
// Web route example Route::get('/autocomplete', [YourController::class, 'autocomplete']); // API route example (if using API middleware) Route::get('/autocomplete', [YourController::class, 'autocomplete'])->middleware('api');
4. Quick Optimizations
- Database Indexes: Add indexes to your
firstname,lastname, andmobilecolumns in theprofilestable to speed up the LIKE queries. - Limit Results: If you have thousands of users, add
->limit(10)to the query to return only top matches (prevents slow loads and cluttered dropdowns). - Full-Text Search: For larger datasets, consider Laravel's built-in full-text search or Laravel Scout with Algolia/Meilisearch for faster, more accurate results.
内容的提问来源于stack exchange,提问作者Falgun Atara
相关产品推荐
相关产品推荐

