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:

Error al indicar que el puerto está asignado.
Error al indicar que el puerto está asignado.

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
Servir la aplicación Laravel con Artisan
Servir la aplicación Laravel con Artisan

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.

Página de bienvenida de la aplicación Laravel
Página de bienvenida de la aplicación Laravel

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 
Hacer una migración llamada create_trains_table
Hacer una migración llamada 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
Aplicar la migración a Artisan
Aplicar la migración a Artisan

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.

Página de Claves API en Algolia Cloud
Página de Claves API en Algolia Cloud

En la página Claves API, observa los valores Application IDAdmin API Key. Utilizarás estas credenciales para autenticar la conexión entre la aplicación Laravel y Algolia.

ID de la aplicación y Claves API del administrador
ID de la aplicación y Claves API del administrador

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.

Datos del modelo de tren
Datos del modelo de tren

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.

Insertar una nueva entrada de tren
Insertar una nueva entrada de tren

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.

Utilizar la función de búsqueda para encontrar una entrada de tren
Utilizar la función de búsqueda para encontrar una entrada de tren

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.

Jeremy Holcombe Kinsta

Editor de Contenidos y Marketing en Kinsta, Desarrollador Web de WordPress y Redactor de Contenidos. Aparte de todo lo relacionado con WordPress, me gusta la playa, el golf y el cine. También tengo problemas con la gente alta ;).