Laravel Query Builder Search (match against)

Stefan Bogdanescu

Founder & Senior Architect · 2026-06-29

Laravel Company

Mastering Full-Text Search in Laravel: Diving into MATCH AGAINST

As a senior developer, I often encounter situations where the elegance of an ORM like Laravel meets the specific, powerful features of the underlying database. You are running into a very common hurdle: wanting to perform advanced full-text search operations, such as MySQL's MATCH() AGAINST() syntax, but finding it absent directly in the standard Eloquent Query Builder documentation.

The short answer is that while Laravel provides excellent tools for abstraction, highly specific database features often require dropping down to raw SQL. Understanding where and how to bridge the gap between your application logic and the database engine is crucial for effective development.

This post will guide you through implementing full-text search functionality in a Laravel application, focusing on using the Query Builder effectively.


The Full-Text Search Dilemma

The query you provided—select *, MATCH(hobbies) AGAINST('soccer' IN BOOLEAN MODE) from users where MATCH(hobbies) AGAINST('soccer' IN BOOLEAN MODE) LIMIT 10 OFFSET 0;—relies entirely on MySQL or MariaDB's Full-Text Search (FTS) capabilities. This functionality is inherent to the database engine, not strictly part of Laravel’s Eloquent syntax.

Laravel’s Query Builder focuses on standard CRUD operations (SELECT, INSERT, UPDATE, DELETE). When you need complex, proprietary SQL functions like MATCH AGAINST, you must use the underlying database connection directly.

Solution 1: Executing Raw Full-Text Queries with DB::raw()

The most direct way to execute this query in Laravel is by leveraging the DB facade and its raw expression methods, specifically whereRaw() or selectRaw(). This allows you to inject your specific SQL commands directly into the query.

Here is how you would structure that search operation:

use Illuminate\Support\Facades\DB;

class UserController extends Controller
{
    public function searchHobbies(string $searchTerm)
    {
        $searchTerm = '%' . $searchTerm . '%'; // Prepare the search term for pattern matching

        $results = DB::table('users')
            ->select('*')
            // Use whereRaw to inject the complex MATCH AGAINST logic
            ->whereRaw("MATCH(hobbies) AGAINST(? IN BOOLEAN MODE)", [$searchTerm])
            ->limit(10)
            ->offset(0)
            ->get();

        return $results;
    }
}

Best Practices for whereRaw()

When using whereRaw(), always treat the input parameters as external data to be safely bound. In the example above, we pass an array ([$searchTerm]) as the second argument. Laravel handles the proper escaping and binding of these variables, which is critical for preventing SQL injection vulnerabilities. This approach keeps your application logic clean while giving you access to powerful database features.

Solution 2: Integrating Search via Eloquent Relationships (Advanced)

While the above method works perfectly, a more "Laravel-idiomatic" approach involves abstracting this search logic into Eloquent scopes. This keeps your models responsible for defining what data is searchable, rather than mixing complex SQL directly in your controllers.

You can define a scope on your User model to handle filtering:

// In app/Models/User.php

public function scopeSearchHobbies($query, string $term)
{
    $sql = "MATCH(hobbies) AGAINST(? IN BOOLEAN MODE)";
    return $query->whereRaw($sql, [$term]);
}

Then, in your controller or service layer, the usage becomes incredibly clean:

$users = User::searchHobbies('soccer')->take(10)->get();

This pattern demonstrates how Laravel allows you to build powerful, reusable query logic. For deeper insights into structuring complex data interactions within the framework, exploring architectural patterns is key—much like understanding how components interact in a robust application built on platforms like Laravel.

Conclusion

Full-text search functionality often requires leveraging native database capabilities rather than relying solely on ORM convenience methods. By mastering the use of DB::raw() and properly binding parameters, you can seamlessly integrate complex SQL features like MATCH AGAINST into your Laravel applications. Remember, when the ORM doesn't provide a direct path, the power lies in understanding how to instruct the database directly. Happy coding!