Full Text Search - Corujalab

Primeiro, cria uma migration pra alterar a tabela de usuários:

php artisan make: migration add_fulltext_search_to_users
<?php

use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;

class AddFulltextSearch extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        \DB::statement("
            ALTER TABLE users ADD FULLTEXT fulltext_index (name);"
        );
    }
}

No campo destacado, tu coloca o nome das colunas que quer pesquisar em qualquer parte da palavra. Nesse exemplo, está apenas na coluna Name da tabela users.

php artisan migrate

Cria um arquivo em \App\Traits chamado FullTextSearch.php com o seguinte código:

<?php
 
namespace App\Traits;
 
trait FullTextSearch
{
    /**
     * Replaces spaces with full text search wildcards
     *
     * @param string $term
     * @return string
     */
    protected function fullTextWildcards($term)
    {
        // removing symbols used by MySQL
        $reservedSymbols = ['-', '+', '<', '>', '@', '(', ')', '~'];
        $term = str_replace($reservedSymbols, '', $term);
 
        $words = explode(' ', $term);
 
        foreach($words as $key => $word) {
            /*
             * applying + operator (required word) only big words
             * because smaller ones are not indexed by mysql
             */
            if(strlen($word) >= 3) {
                $words[$key] = '+' . $word . '*';
            }
        }
 
        $searchTerm = implode( ' ', $words);
 
        return $searchTerm;
    }
 
    /**
     * Scope a query that matches a full text search of term.
     *
     * @param \Illuminate\Database\Eloquent\Builder $query
     * @param string $term
     * @return \Illuminate\Database\Eloquent\Builder
     */
    public function scopeSearch($query, $term)
    {
        $columns = implode(',',$this->searchable);
 
        $query
            ->whereRaw("MATCH ({$columns}) AGAINST (? IN BOOLEAN MODE)" , $this->fullTextWildcards($term))
            ->orWhere('email', 'like', '%'. $term . '%');
 
        return $query;
    }
}

Aqui, estamos pesquisando tanto com o Full Text Search na coluna Name, quanto com like na coluna e-mail.

Na Model User, tu adiciona o seguinte:

<?php

namespace App\Models;

use Illuminate\Notifications\Notifiable;
use Illuminate\Foundation\Auth\User as Authenticatable;
use \App\Notifications\ResetPassword as ResetPasswordNotification;
use \App\Traits\FullTextSearch;

class User extends Authenticatable
{
    use Notifiable;
    use FullTextSearch;

    public $remember_token = false;

    /**
     * The attributes that are mass assignable.
     *
     * @var array
     */
    protected $fillable = [
        'id', 'name', 'email', 'password', 'logins', 'last_login'
    ];

    /**
     * The attributes that should be hidden for arrays.
     *
     * @var array
     */
    protected $hidden = [
        'password', 'remember_token',
    ];

    protected $date = ['last_login'];

    protected $searchable = [
        'name'
    ];

    public function sendPasswordResetNotification($token)
    {
        $this->notify(new ResetPasswordNotification($token));
    }

    public function Role()
    {
        return $this->belongsToMany(Role::class, 'role_users');
    }
}

No teu UsersController, tu adiciona o seguinte:

public function search(Request $request, $term)
    {
        $users = \App\Models\User::search($term)
                ->get()
                ->take(10);
        
dd($users); // Aqui está retornando em um json a lista, considerando que tu vai fazer uma chamada via ajax ao digitar em um input,

        return json_encode(['success' => true, 'users' => $users]);

    }

E por último, cria uma rota com:

Route::post('/pesquisa-usuario/{term}', ['uses' => 'UsersController@search', 'as' => 'app.users.search']);