El framework Laravel se ha convertido en un recurso de referencia para los desarrolladores que crean servicios web.
Como herramienta de código abierto, Laravel ofrece un sinfín de funcionalidades listas para usar que permiten a los desarrolladores crear aplicaciones robustas y funcionales.
Entre sus ofertas está Laravel Scout, una biblioteca para gestionar los índices de búsqueda de tu aplicación. Su flexibilidad permite a los desarrolladores afinar las configuraciones y seleccionar entre los controladores Algolia, Meilisearch, MySQL o Postgres para almacenar los índices.
Aquí exploraremos esta herramienta en profundidad, enseñándote cómo añadir soporte de búsqueda de texto completo a una aplicación Laravel a través del controlador. Modelaremos una aplicación Laravel de demostración para almacenar el nombre de trenes ficticios y luego usaremos Laravel Scout para añadir una búsqueda a la aplicación.
Prerrequisitos
Para seguir adelante, debes tener:
- El compilador PHP instalado en tu ordenador. Este tutorial utiliza la versión 8.1 de PHP.
- El motor Docker o Docker Desktop instalado en tu ordenador
- Una cuenta Algolia en la nube, que puedes crear gratuitamente
Cómo Instalar Scout en un Proyecto Laravel
Para utilizar Scout, primero debes crear una aplicación Laravel en la que pretendas añadir la funcionalidad de búsqueda. El script Laravel-Scout Bash contiene los comandos para generar una aplicación Laravel dentro de un contenedor Docker. Utilizar Docker significa que no necesitas instalar software de soporte adicional, como una base de datos MySQL.
El script Laravel-scout utiliza el lenguaje de scripting Bash, por lo que debes ejecutarlo dentro de un entorno Linux. Si utilizas Windows, asegúrate de configurar el Subsistema de Windows para Linux (WSL).
Si utilizas WSL, ejecuta el siguiente comando en tu terminal para configurar tu distribución de Linux preferida.
wsl -s ubuntu
A continuación, navega hasta la ubicación de tu ordenador en la que quieras colocar el proyecto. El script Laravel-Scout generará un directorio de proyecto aquí. En el ejemplo siguiente, el script Laravel-Scout creará un directorio dentro del directorio desktop.
cd /desktop
Ejecuta el siguiente comando para ejecutar el script Laravel-Scout. Creará una aplicación Dockerizada con el código boilerplate necesario.
curl -s https://laravel.build/laravel-scout-app | bash
Tras la ejecución, cambia de directorio utilizando cd laravel-scout-app
. A continuación, ejecuta el comando sail-up
dentro de la carpeta del proyecto para iniciar los contenedores Docker de tu aplicación.
Nota: En muchas distribuciones de Linux, puede que necesites ejecutar el comando que aparece a continuación con el comando sudo
para iniciar privilegios elevados.
./vendor/bin/sail up
Es posible que te encuentres con un error:
Para resolverlo, utiliza la variable APP_PORT
para especificar un puerto dentro del comando sail up
:
APP_PORT=3001 ./vendor/bin/sail up
A continuación, ejecuta el siguiente comando para ejecutar la aplicación a través de Artisan en el servidor PHP.
php artisan serve
Desde tu navegador web, navega a la aplicación en ejecución en http://127.0.0.1:8000. La aplicación mostrará la página de bienvenida de Laravel en la ruta por defecto.
Cómo Añadir Laravel Scout a la Aplicación
En tu terminal, introduce el comando para habilitar el gestor de paquetes PHP Composer para añadir Laravel Scout al proyecto.
composer require laravel/scout
A continuación, publica el archivo de configuración de Scout utilizando el comando vendor:publish. El comando publicará el archivo de configuración scout.php
en el directorio config de tu aplicación.
php artisan vendor:publish --provider="LaravelScoutScoutServiceProvider"
Ahora, modifica el archivo boilerplate .env para que contenga un valor booleano SCOUT_QUEUE
.
El valor SCOUT_QUEUE
permitirá a Scout poner en cola las operaciones, proporcionando mejores tiempos de respuesta. Sin él, los controladores de Scout como Meilisearch no reflejarán los nuevos registros inmediatamente.
SCOUT_QUEUE=true
Además, modifica la variable DB_HOST
en el archivo .env para que apunte a tu localhost para utilizar la base de datos MySQL dentro de los contenedores Docker.
DB_HOST=127.0.0.1
Cómo Marcar un Modelo y Configurar el ndice
Scout no habilita por defecto los modelos de datos con opción de búsqueda. Debes marcar explícitamente un modelo como buscable utilizando su rasgo LaravelScoutSearchable
.
Empezarás creando un modelo de datos para una aplicación Train
de demostración y marcándolo como buscable.
Cómo crear un modelo
Para la aplicación Train
, querrás almacenar los nombres de los marcadores de posición de cada tren disponible.
Ejecuta el siguiente comando de Artisan para generar la migración y nómbrala create_trains_table
.
php artisan make:migration create_trains_table
La migración se generará en un archivo cuyo nombre combina el nombre especificado y la marca de tiempo actual.
Abre el archivo de migración situado en el directorio database/migrations/.
Para añadir una columna de título, añade el siguiente código después de la columna id()
en la línea 17. El código añadirá una columna de título.
$table->string('title');
Para aplicar la migración, ejecuta el comando siguiente.
php artisan migrate
Después de ejecutar las migraciones de la base de datos, crea un archivo llamado Train.php en el directorio app/Models/.
Cómo añadir el trait LaravelScoutSearchable
Marca el modelo Train
para la búsqueda añadiendo el rasgo LaravelScoutSearchable
al modelo, como se muestra a continuación.
<?php
namespace AppModels;
use IlluminateDatabaseEloquentModel;
use LaravelScoutSearchable;
class Train extends Model
{
use Searchable;
public $fillable = ['title'];
Además, tienes que configurar los índices de búsqueda anulando el método searchable
. El comportamiento por defecto de Scout sería persistir en el modelo para que coincida con el nombre de la tabla del modelo.
Por lo tanto, añade el siguiente código al archivo Train.php debajo del código del bloque anterior.
/**
* Retrieve the index name for the model.
*
* @return string
*/
public function searchableAs()
{
return 'trains_index';
}
}
Cómo Utilizar Algolia con Scout
Para la primera búsqueda de texto completo con Laravel Scout, utilizarás el controlador Algolia. Algolia es una plataforma de software como servicio (SaaS) que se utiliza para buscar en grandes cantidades de datos. Proporciona un panel web para que los desarrolladores gestionen sus índices de búsqueda y una sólida API a la que puedes acceder mediante un kit de desarrollo de software (SDK) en tu lenguaje de programación preferido.
Dentro de la aplicación Laravel, utilizarás el paquete cliente Algolia para PHP.
Cómo configurar Algolia
En primer lugar, debes instalar el paquete cliente de búsqueda Algolia para PHP para tu aplicación.
Ejecuta el siguiente comando.
composer require algolia/algoliasearch-client-php
A continuación, debes establecer el ID de tu aplicación y las credenciales secretas de la clave API de Algolia en el archivo .env.
Utilizando tu navegador web, navega a tu panel de control de Algolia para obtener las credenciales de ID de Aplicación y Clave Secreta de API.
Haz clic en Settings en la parte inferior de la barra lateral izquierda para navegar a la página de Settings.
A continuación, haz clic en API Keys dentro de la sección Team and Access de la página Configuración para ver las claves de tu cuenta de Algolia.
En la página Claves API, observa los valores Application ID y Admin API Key. Utilizarás estas credenciales para autenticar la conexión entre la aplicación Laravel y Algolia.
Añade el código siguiente a tu archivo .env utilizando tu editor de código y sustituye los marcadores de posición por los secretos de API de Algolia correspondientes.
ALGOLIA_APP_ID=APPLICATION_ID
ALGOLIA_SECRET=ADMIN_API_KEY
Además, sustituye la variable SCOUT_DRIVER
por el código siguiente para cambiar el valor de meilisearch
a algolia
. El cambio de este valor indicará a Scout que utilice el controlador de Algolia.
SCOUT_DRIVER=algolia
Cómo Crear los Controladores de la Aplicación
Dentro del directorio app/Http/Controllers/, crea un archivo TrainSearchController.php para almacenar un controlador para la aplicación. El controlador listará y añadirá datos al modelo Train
.
Añade el siguiente bloque de código en el archivo TrainSearchController.php para crear el controlador.
<?php
namespace AppHttpControllers;
use IlluminateHttpRequest;
use AppHttpRequests;
use AppModelsTrain;
class TrainSearchController extends Controller
{
/**
* Get the index name for the model.
*
* @return string
*/
public function index(Request $request)
{
if($request->has('titlesearch')){
$trains = Train::search($request->titlesearch)
->paginate(6);
}else{
$trains = Train::paginate(6);
}
return view('Train-search',compact('trains'));
}
/**
* Get the index name for the model.
*
* @return string
*/
public function create(Request $request)
{
$this->validate($request,['title'=>'required']);
$trains = Train::create($request->all());
return back();
}
}
Cómo Crear las Rutas de la Aplicación
En este paso, crearás las rutas para listar y añadir nuevos trenes a la base de datos.
Abre tu archivo routes/web.php y sustituye el código existente por el bloque que aparece a continuación.
<?php
use IlluminateSupportFacadesRoute;
use AppHttpControllersTrainSearchController;
Route::get('/', function () {
return view('welcome');
});
Route::get('trains-lists', [TrainSearchController::class, 'index']) -> name ('trains-lists');
Route::post('create-item', [TrainSearchController::class, 'create']) -> name ('create-item');
El código anterior define dos rutas en la aplicación. La petición GET
para la ruta /trains-lists
lista todos los datos de trenes almacenados. La petición POST
para la ruta /create-item
crea nuevos datos del tren.
Cómo Crear las Vistas de la Aplicación
Crea un archivo dentro del directorio resources/views/ y llámalo Train-search.blade.php. El archivo mostrará la interfaz de usuario para la funcionalidad de búsqueda.
Añade el contenido del bloque de código siguiente en el archivo Train-search.blade.php para crear una página única para la funcionalidad de búsqueda.
<!DOCTYPE html>
<html>
<head>
<title>Laravel - Laravel Scout Algolia Search Example</title>
<link rel="stylesheet" type="text/css" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
</head>
<body>
<div class="container">
<h2 class="text-bold">Laravel Full-Text Search Using Scout </h2><br/>
<form method="POST" action="{{ route('create-item') }}" autocomplete="off">
@if(count($errors))
<div class="alert alert-danger">
<strong>Whoops!</strong> There is an error with your input.
<br/>
<ul>
@foreach($errors->all() as $error)
<li>{{ $error }}</li>
@endforeach
</ul>
</div>
@endif
<input type="hidden" name="_token" value="{{ csrf_token() }}">
<div class="row">
<div class="col-md-6">
<div class="form-group {{ $errors->has('title') ? 'has-error' : '' }}">
<input type="text" id="title" name="title" class="form-control" placeholder="Enter Title" value="{{ old('title') }}">
<span class="text-danger">{{ $errors->first('title') }}</span>
</div>
</div>
<div class="col-md-6">
<div class="form-group">
<button class="btn btn-primary">Create New Train</button>
</div>
</div>
</div>
</form>
<div class="panel panel-primary">
<div class="panel-heading">Train Management</div>
<div class="panel-body">
<form method="GET" action="{{ route('trains-lists') }}">
<div class="row">
<div class="col-md-6">
<div class="form-group">
<input type="text" name="titlesearch" class="form-control" placeholder="Enter Title For Search" value="{{ old('titlesearch') }}">
</div>
</div>
<div class="col-md-6">
<div class="form-group">
<button class="btn btn-primary">Search</button>
</div>
</div>
</div>
</form>
<table class="table">
<thead>
<th>Id</th>
<th>Train Title</th>
<th>Creation Date</th>
<th>Updated Date</th>
</thead>
<tbody>
@if($trains->count())
@foreach($trains as $key => $item)
<tr>
<td>{{ ++$key }}</td>
<td>{{ $item->title }}</td>
<td>{{ $item->created_at }}</td>
<td>{{ $item->updated_at }}</td>
</tr>
@endforeach
@else
<tr>
<td colspan="4">No train data available</td>
</tr>
@endif
</tbody>
</table>
{{ $trains->links() }}
</div>
</div>
</div>
</body>
</html>
El código HTML anterior contiene un elemento de formulario con un campo de entrada y un botón para escribir el título de un tren antes de guardarlo en la base de datos. El código también contiene una tabla HTML que muestra los detalles id, title, created_at y updated_at de una entrada de tren dentro de la base de datos.
Cómo Utilizar la Búsqueda Algolia
Para ver la página, navega a http://127.0.0.1:8000/trains-lists desde tu navegador web.
La base de datos está actualmente vacía, por lo que debes introducir el título de un tren de demostración en el campo de entrada y hacer clic en Crear nuevo tren para guardarlo.
Para utilizar la función de búsqueda, escribe una palabra clave de cualquiera de los títulos de tren guardados en el campo de entrada Introducir título para la búsqueda y haz clic en Buscar.
Como se muestra en la imagen siguiente, sólo se mostrarán las entradas de búsqueda que contengan la palabra clave en sus títulos.
Meilisearch con Laravel Scout
Meilisearch es un motor de búsqueda de código abierto centrado en la velocidad, el rendimiento y la mejora de la experiencia del desarrollador. Comparte varias características con Algolia, utilizando los mismos algoritmos, estructuras de datos e investigación, pero con un lenguaje de programación diferente.
Los desarrolladores pueden crear y autoalojar una instancia de Meilisearch dentro de su infraestructura local o en la nube. Meilisearch también tiene una oferta beta en la nube similar a Algolia para los desarrolladores que quieran utilizar el producto sin gestionar su infraestructura.
En el tutorial, ya tienes una instancia local de Meilisearch ejecutándose dentro de tus contenedores Docker. Ahora ampliarás la funcionalidad de Laravel Scout para utilizar la instancia de Meilisearch.
Para añadir Meilisearch a la aplicación Laravel, ejecuta el siguiente comando en el terminal de tu proyecto.
composer require meilisearch/meilisearch-php
A continuación, tienes que modificar las variables de Meilisearch dentro del archivo .env para configurarlo.
Sustituye las variables SCOUT_DRIVER
, MEILISEARCH_HOST
, y MEILISEARCH_KEY
del archivo . env por las que aparecen a continuación.
SCOUT_DRIVER=meilisearch
MEILISEARCH_HOST=http://127.0.0.1:7700
MEILISEARCH_KEY=LockKey
La clave SCOUT_DRIVER
especifica el controlador que debe utilizar Scout, mientras que MEILISEARCH_HOST
representa el dominio donde se ejecuta tu instancia de Meilisearch. Aunque no es necesario durante el desarrollo, se recomienda añadir la MEILISEARCH_KEY
en producción.
Nota: Comenta el ID y el Secreto de Algolia cuando utilices Meilisearch como tu controlador preferido.
Una vez completadas las configuraciones .env, debes indexar tus registros preexistentes utilizando el comando Artisan que se indica a continuación.
php artisan scout:import "AppModelsTrain"
Laravel Scout con el Motor de Base de Datos
El motor de la base de datos de Scout puede ser más adecuado para aplicaciones que utilizan bases de datos más pequeñas o gestionan cargas de trabajo menos intensivas. Actualmente, el motor de base de datos soporta PostgreSQL y MySQL.
Este motor utiliza cláusulas «where-like» e índices de texto completo contra tu base de datos existente, lo que le permite encontrar los resultados de búsqueda más relevantes. No necesitas indexar tus registros cuando utilices el motor de base de datos.
Para utilizar el motor de base de datos, debes establecer tu variable SCOUT_DRIVER
.env en la base de datos.
Abre el archivo .env dentro de la aplicación Laravel y cambia el valor de la variable SCOUT_DRIVER
.
SCOUT_DRIVER = database
Después de cambiar tu controlador a la base de datos, Scout pasará a utilizar el motor de base de datos para la búsqueda de texto completo.
Motor de Colección con Laravel Scout
Además del motor de base de datos, Scout también ofrece un motor de colección. Este motor utiliza cláusulas «where» y filtrado de colecciones para extraer los resultados de búsqueda más relevantes.
A diferencia del motor de base de datos, el motor de colecciones admite todas las bases de datos relacionales que también admite Laravel.
Puedes utilizar el motor de rolección estableciendo la variable de entorno SCOUT_DRIVER
en collection
o especificando manualmente el motor de recolección en el archivo de configuración de Scout.
SCOUT_DRIVER = collection
Explorer con Elasticsearch
Con la fuerza de las consultas de Elasticsearch, Explorer es un moderno controlador de Elasticsearch para Laravel Scout. Ofrece un controlador Scout compatible y ventajas como almacenar, buscar y analizar cantidades masivas de datos en tiempo real. Elasticsearch con Laravel ofrece resultados en milisegundos.
Para utilizar el controlador Elasticsearch Explorer en tu aplicación Laravel, tendrás que configurar el archivo boilerplate docker-compose.yml que generó el script Laravel-Scout. Añadirás las configuraciones adicionales para Elasticsearch y reiniciarás los contenedores.
Abre tu archivo docker-compose.yml y sustituye su contenido por lo siguiente.
# For more information: https://laravel.com/docs/sail
version: '3'
services:
laravel.test:
build:
context: ./vendor/laravel/sail/runtimes/8.1
dockerfile: Dockerfile
args:
WWWGROUP: '${WWWGROUP}'
image: sail-8.1/app
extra_hosts:
- 'host.docker.internal:host-gateway'
ports:
- '${APP_PORT:-80}:80'
- '${VITE_PORT:-5173}:${VITE_PORT:-5173}'
environment:
WWWUSER: '${WWWUSER}'
LARAVEL_SAIL: 1
XDEBUG_MODE: '${SAIL_XDEBUG_MODE:-off}'
XDEBUG_CONFIG: '${SAIL_XDEBUG_CONFIG:-client_host=host.docker.internal}'
volumes:
- '.:/var/www/html'
networks:
- sail
depends_on:
- mysql
- redis
- meilisearch
- mailhog
- selenium
- pgsql
- elasticsearch
mysql:
image: 'mysql/mysql-server:8.0'
ports:
- '${FORWARD_DB_PORT:-3306}:3306'
environment:
MYSQL_ROOT_PASSWORD: '${DB_PASSWORD}'
MYSQL_ROOT_HOST: "%"
MYSQL_DATABASE: '${DB_DATABASE}'
MYSQL_USER: '${DB_USERNAME}'
MYSQL_PASSWORD: '${DB_PASSWORD}'
MYSQL_ALLOW_EMPTY_PASSWORD: 1
volumes:
- 'sail-mysql:/var/lib/mysql'
- './vendor/laravel/sail/database/mysql/create-testing-database.sh:/docker-entrypoint-initdb.d/10-create-testing-database.sh'
networks:
- sail
healthcheck:
test: ["CMD", "mysqladmin", "ping", "-p${DB_PASSWORD}"]
retries: 3
timeout: 5s
elasticsearch:
image: 'elasticsearch:7.13.4'
environment:
- discovery.type=single-node
ports:
- '9200:9200'
- '9300:9300'
volumes:
- 'sailelasticsearch:/usr/share/elasticsearch/data'
networks:
- sail
kibana:
image: 'kibana:7.13.4'
environment:
- elasticsearch.hosts=http://elasticsearch:9200
ports:
- '5601:5601'
networks:
- sail
depends_on:
- elasticsearch
redis:
image: 'redis:alpine'
ports:
- '${FORWARD_REDIS_PORT:-6379}:6379'
volumes:
- 'sail-redis:/data'
networks:
- sail
healthcheck:
test: ["CMD", "redis-cli", "ping"]
retries: 3
timeout: 5s
pgsql:
image: 'postgres:13'
ports:
- '${FORWARD_DB_PORT:-5432}:5432'
environment:
PGPASSWORD: '${DB_PASSWORD:-secret}'
POSTGRES_DB: '${DB_DATABASE}'
POSTGRES_USER: '${DB_USERNAME}'
POSTGRES_PASSWORD: '${DB_PASSWORD:-secret}'
volumes:
- 'sailpgsql:/var/lib/postgresql/data'
networks:
- sail
healthcheck:
test: ["CMD", "pg_isready", "-q", "-d", "${DB_DATABASE}", "-U", "${DB_USERNAME}"]
retries: 3
timeout: 5s
meilisearch:
image: 'getmeili/meilisearch:latest'
ports:
- '${FORWARD_MEILISEARCH_PORT:-7700}:7700'
volumes:
- 'sail-meilisearch:/meili_data'
networks:
- sail
healthcheck:
test: ["CMD", "wget", "--no-verbose", "--spider", "http://localhost:7700/health"]
retries: 3
timeout: 5s
mailhog:
image: 'mailhog/mailhog:latest'
ports:
- '${FORWARD_MAILHOG_PORT:-1025}:1025'
- '${FORWARD_MAILHOG_DASHBOARD_PORT:-8025}:8025'
networks:
- sail
selenium:
image: 'selenium/standalone-chrome'
extra_hosts:
- 'host.docker.internal:host-gateway'
volumes:
- '/dev/shm:/dev/shm'
networks:
- sail
networks:
sail:
driver: bridge
volumes:
sail-mysql:
driver: local
sail-redis:
driver: local
sail-meilisearch:
driver: local
sailpgsql:
driver: local
sailelasticsearch:
driver: local
A continuación, ejecuta el siguiente comando para extraer la nueva imagen de Elasticsearch que has añadido al archivo docker-compose.yml
docker-compose up
A continuación, ejecuta el siguiente comando de Composer para instalar Explorer en el proyecto.
composer require jeroen-g/explorer
También tienes que crear un archivo de configuración para el controlador de Explorer.
Ejecuta el comando Artisan que aparece a continuación para generar un archivo explorer.config para almacenar las configuraciones.
php artisan vendor:publish --tag=explorer.config
El archivo de configuración generado anteriormente estará disponible en el directorio /config.
En tu archivo config/explorer.php, puedes hacer referencia a tu modelo utilizando la clave indexes
.
'indexes' => [
AppModelsTrain::class
],
Cambia el valor de la variable SCOUT_DRIVER
dentro del archivo .env a elastic
para configurar Scout para que utilice el controlador Explorer.
SCOUT_DRIVER = elastic
En este punto, utilizarás Explorer dentro del modelo Train
implementando la interfaz Explorer y sobrescribiendo el método mappableAs()
.
Abre el archivo Train. php dentro del directorio App > Models y sustituye el código existente por el código que aparece a continuación.
<?php
namespace AppModels;
use IlluminateDatabaseEloquentFactoriesHasFactory;
use IlluminateDatabaseEloquentModel;
use JeroenGExplorerApplicationExplored;
use LaravelScoutSearchable;
class Train extends Model implements Explored
{
use HasFactory;
use Searchable;
protected $fillable = ['title'];
public function mappableAs(): array
{
return [
'id'=>$this->Id,
'title' => $this->title,
];
}
}
Con el código que has añadido arriba, ahora puedes utilizar el Explorador para buscar texto dentro del modelo Train
.
Resumen
Para los desarrolladores de PHP, Laravel y add-ons como Scout hacen que sea pan comido integrar una funcionalidad de búsqueda de texto completo rápida y robusta. Con el motor de base de datos, el motor de colecciones y las capacidades de Meilisearch y Elasticsearch, puedes interactuar con la base de datos de tu aplicación e implementar mecanismos de búsqueda avanzada en apenas milisegundos.
Gestionar y actualizar sin problemas tu base de datos significa que tus usuarios reciben una experiencia óptima mientras tu código permanece limpio y eficiente.
Con nuestras soluciones de alojamiento de aplicaciones y bases de datos, Kinsta es tu solución integral para todas tus necesidades de desarrollo de Laravel moderno. Los primeros 20 dólares corren de nuestra cuenta.
Deja una respuesta