Laravel es un framework battery-incluided de PHP que nos permite crear páginas y aplicaciones web de forma ágil y robusta. Nos proporciona las herramientas fiables necesarias para no reinventar la rueda.
Laravel es un framework que utiliza el patrón MVC, esto es, que cuando alguien hace una petición a nuestro servidor (por ejemplo la ruta https://miservidor.com/recetas), este extrae la URL /recetas
y lo enruta hacia un controlador.
El controlador es simplemente una función que se ejecuta y normalmente tiene una lógica para responder a esta petición. Entre otras cosas el controlador puede interactuar con una base de datos mediante una abstraccion que suele ser nuestro modelo. En este ejemplo nuestras recetas serán nuestros modelos.
Por último normalmente el MVC responde con una vista, pero en el caso de nuestra API REST vamos a devolver datos en formato JSON.
En nuestro ejemplo la respuesta a la petición se vería similar a esto:
[
{
"titulo": "Tortilla de patatas",
"descripcion": "Una breve descripción sobre como hacer una tortilla de patatas",
"dificultad": 3
},
{
"titulo": "Tarta de queso",
"descripcion": "Otra descripción para cocinar una tarta de queso",
"dificultad": 7
},
]
Primero debemos tener instalado PHP y Composer en nuestra máquina. Aquí tenemos una guía de instalación https://laravel.com/docs/12.x/installation#creating-a-laravel-project
Si tenemos los requisitos podemos simplemente ejecutar lo siguiente para crear el proyecto:
composer global require laravel/installer
laravel new example-app
Una vez creado podemos iniciar nuestro servidor de desarollo haciendo:
cd ./example-app
php artisan serve
Tendremos nuestro servidor corriendo, por defecto, en http://localhost:8000
. Podemos inspeccionar esta ruta con nuestro navegador. Esto sería equivalente a hacer una peticion GET a la ruta /
de nuestro proyecto.
En Laravel, un recurso es el conjunto de archivos que necesitas para un modelo (migración , modelo, controlador).
Con el CLI de laravel es muy fácil de generar el esqueleto para estos archivos. Simplemente debemos escribir el siguiente comando:
php artisan make:model Receta -mcr
Esto nos habrá generado los archivos necesarios para poder trabajar con nuestras recetas:
1. database/migrations/xxxx_create_recetas_table.php
2. app/Models/Receta.php
3. app/Http/Controllers/RecetaController.php
En nuestro fichero de database/migration/xxxx_create_recetas_table.php agregaremos lo siguiente:
Schema::create('recetas', function (Blueprint $table) {
$table->id();
$table->string('titulo');
$table->text('descripcion')->nullable();
$table->integer('dificultad')->default(1);
$table->timestamps();
});
Podemos agregar diferentes tipos de columnas para cada campo, aquí tenemos un listado de todas las posiblidades: https://laravel.com/docs/12.x/migrations#columns . Además podremos agregar las típicas restricciones e indices de nuestro gestor de bases de datos.
Laravel utiliza un archivo llamado .env (ubicado en la raíz del proyecto) para definir variables de entorno, como la conexión a la base de datos.
En tu caso, antes de correr las migraciones, edita este archivo y ajusta la sección de base de datos a tu configuración:
Para SQLITE
DB_CONNECTION=sqlite`
DB_DATABASE=/absolute/path/to/database.sqlite
Para MySQL
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=mi_basedatos
DB_USERNAME=mi_usuario
DB_PASSWORD=mi_password
Aquí hay más datos sobre la configuración de la base de datos: https://laravel.com/docs/12.x/database
A continuación para crear nuestra tabla solo tenemos que ejecutar el siguiente comando en la raiz de nuestro proyecto.
php artisan migrate
En app/Models/Receta.php
agrega dos propiedades:
**$table** es el nombre de nuestra tabla
** $fillable** son los campos de nuestro modelo que podemos poblar de forma másiva.
Los campos no agregados en $fillable solo podrán ser modificados uno a uno de forma explicita.
class Receta extends Model
{
protected $table = 'recetas';
protected $fillable = ['titulo', 'descripcion', 'dificultad'];
}
Además de esto podemos agregar métodos para crear funcionalidades que podremos llamar usando directamente el modelo o relaciones con otros modelos siguiendo estas instrucciones: https://laravel.com/docs/12.x/eloquent-relationships#main-content .
Ahora es hora de modificar nuestro controlador en app/Http/Controllers/RecetaController.php
. Dentro haremos los distintos métodos típicos para tener listo nuestro CRUD (Create/Read/Update/Delete).
1. index: Lista todas las recetas.
2. show: Muestra la lista con el id pasado.
3. store: Crear una receta partir de unos datos proporcionados.
4. update: Actualiza una receta con unos datos proporcionados.
5. delete: Eliminar una receta.
namespace App\Http\Controllers;
use App\Models\Receta;
use Illuminate\Http\Request;
class RecetaController extends Controller
{
// GET /api/recetas
public function index()
{
return Receta::all();
}
// GET /api/recetas/{id}
public function show($id)
{
return Receta::findOrFail($id);
}
// POST /api/recetas
public function store(Request $request)
{
$receta = Receta::create($request->all());
return response()->json($receta, 201);
}
// PUT /api/recetas/{id}
public function update(Request $request, $id)
{
$receta = Receta::findOrFail($id);
$receta->update($request->all());
return $receta;
}
// DELETE /api/recetas/{id}
public function destroy($id)
{
Receta::destroy($id);
return response()->json(null, 204);
}
}
Un elemento clave de Laravel es que podemos usar su servicio de inyección de dependencias automático para facilitar este proceso.
Si tipamos con el modelo los métodos de nuestro controlador y rutas, estos se transformarán automáticamente en la instancia de este modelo y te manejará automáticamente los errores 404 si no lo encuentra.
namespace App\Http\Controllers;
use App\Models\Receta;
use Illuminate\Http\Request;
class RecetaController extends Controller
{
// GET /api/recetas
public function index()
{
return Receta::all();
}
// GET /api/recetas/{receta}
public function show(Receta $receta)
{
return $receta;
}
// POST /api/recetas
public function store(Request $request)
{
$receta = Receta::create($request->all());
return response()->json($receta, 201);
}
// PUT /api/recetas/{receta}
public function update(Request $request, Receta $receta)
{
$receta->update($request->all());
return $receta;
}
// DELETE /api/recetas/{receta}
public function destroy(Receta $receta)
{
$receta->delete();
return response()->json(null, 204);
}
}
Un detalle extra, Eloquent permite hacer ->paginate() sobre nuestros modelos para devolver una respuesta paginada en chunks de forma automática. Mas información; https://laravel.com/docs/12.x/pagination#main-content
En routes/api.php
agregamos lo siguiente:
use App\Http\Controllers\RecetaController;
Route::get('/recetas', [RecetaController::class, 'index']);
Route::get('/recetas/{id}', [RecetaController::class, 'show']); // sin tipado
Route::post('/recetas', [RecetaController::class, 'store']);
Route::put('/recetas/{id}', [RecetaController::class, 'update']);
Route::delete('/recetas/{id}', [RecetaController::class, 'destroy']);
Si usamos el Route Model Binding, basta con cambiar {id}
→ {receta}
para tiparlo en nuestro controlador:
Route::get('/recetas/{receta}', [RecetaController::class, 'show']);
Route::put('/recetas/{receta}', [RecetaController::class, 'update']);
Route::delete('/recetas/{receta}', [RecetaController::class, 'destroy']);
Además si usamos los nombres por defecto index, show, store, update, destroy podemos simplificar más aún nuestras rutas en esto:
use App\Http\Controllers\RecetaController;
Route::apiResource('recetas', RecetaController::class);
Quizás queramos tener nuestra API abierta al público, pero suele ser habitual restringuir el acceso con algún mecanismo de autorización.
Lo más sencillo es usar Laravel Sanctum (para tokens simples), más adelante podemos cambiarlo por otros mecanismos más sofisticados. Pero veamos como se haría de esta forma.
Primero debemos instalar las dependencias necesarias:
composer require laravel/sanctum
php artisan migrate
Ahora tenemos que decirle a Laravel que los modelos de usuario que usamos para autentificarnos van a usar estos tokens. Normalmente usaremos los usuarios por defecto en app/Models/User.php
. Debemos modificarlo agregando el siguiente trait:
use Laravel\Sanctum\HasApiTokens;
class User extends Authenticatable
{
...
use HasApiTokens;
...
}
Teniendo esto ya podemos asegurar las rutas que queramos, como por ejemplo:
Route::middleware('auth:sanctum')->group(function () {
# Aqui dentro agregamos las rutas protegidas
Route::apiResource('recetas', RecetaController::class);
});
Si queremos generar este token en un método login podemos usar el siguiente snippet:
$user = User::where('email', $request->email)->first();
if ($user && Hash::check($request->password, $user->password)) {
return $user->createToken('miapi')->plainTextToken;
}
Del lado del cliente, para poder autentificarnos, deberemos enviar la siguiente cabecera. En caso contrario, nos dará un error 401 No Autorizado.
Authorization: Bearer TOKEN_GENERADO
Para ampliar información de Sanctum seguir el siguiente enlace: https://laravel.com/docs/12.x/sanctum#api-token-authentication
Por ultimo podemos desplegar nuestra API REST simplemente siguiendo las recomendaciones de Laravel: https://laravel.com/docs/12.x/deployment#main-content .
Nos proporciona una plantilla de configuracion para Nginx y solo debemos actualizar los campos pertinentes a nuestro proyecto.
Además es mejor optimizar todos los ficheros necesarios con php artisan optimize
Después de realizar los cambios siempre debemos reiniciar nuestro nginx para que tomen efecto.
sudo systemctl reload nginx
Para ampliar información de como servir una web puedes ver mi articulo: https://www.ksergio.com/servir-pagina-web-nginx