Instalación del entorno necesario
1. Instalamos Laragon Full.
2. Instalamos composer
3. Instalamos globalmente el creador de proyectos de Laravel ejecutando en la terminal el siguiente comando:
composer global require laravel/installer
3. Para probar, podemos ir a localhost.
Creación de un proyecto en Laravel
1. Ejecutamos el siguiente comando dentro de c:/laragon/www para crear nuestro proyecto de Laravel:
laravel new example-app
2. Desde el panel de administración de Laragon, recargamos el apache para que detecte el proyecto que acabamos de crear.
3. Ingresamos en: example-app.test
Ficheros y carpetas fundamentales de una aplicación Laravel
- app. Aquí estan los ficheros que nosotros estamos desarrollando. Aquí pasaremos la mayor parte del tiempo.
- Http/Controllers: Esta es la capa que procesa las solicitudes del usuario.
- Http/Middleware: Nos permiten atrapar una petición y hacer alguna validación adicional, inyectar código, etc.
- models. Se comunican con tablas de la base de datos para gestionarlas.
- routes: Aquí están las rutas correspondientes a las peticiones del cliente.
- vendor: Aquí está todo el código que necesita Laravel para poder funcionar, es decir, el propio framework y sus dependencias.
Componentes fundamentales de un proyecto con Laravel
- model → representan la estructura y la interacción con la base de datos. Proporcionan métodos para realizar operaciones de base de datos, como consultas, inserciones, actualizaciones y eliminaciones.
php artisan make:model Book
- controller → manejan la lógica de la aplicación y actúan como intermediarios entre las rutas y los modelos. Reciben solicitudes HTTP, interactúan con los modelos y devuelven una respuesta al cliente.
php artisan make:controller BookController
- seeder → permiten poblar la base de datos con datos de prueba o iniciales.
php artisan make:seeder BookSeeder
- migration → son documentos escritos en PHP que serán traducidos en tablas de la base de datos.
php artisan make:migration create_books_table
- factory → se utilizan para generar datos de prueba de manera rápida y automatizada. Son útiles para crear registros falsos en la base de datos durante las pruebas o para llenar la base de datos con datos de prueba.
La siguiente instrucción creará todos los componentes anteriores ficheros (aunque Book esta en singular, la tabla de la base de datos será creada en plural):
php artisan make:model Book -a
La siguiente instrucción creará un modelo, una migración y un seeder:
php artisan make:model Book -ms
Enrutamiento
Controller
Para crear las rutas editaremos el fichero routes/api.php:
use App\Http\Controllers\Api\BookController
...
// Es SUPER IMPORTANTE que la siguiente url no termine en barra
Route::get('/book', [BookController::class, 'index']);
Route::get('/book/{id}', [BookController::class, 'getById']);
Si con el navegador accedemos a la ruta http://laraapp.test/api/brand, deberíamos ver una página en blanco.
BookController.php
<?php
namespace App\Http\Controllers\Api;
use App\Http\Controllers\Controller;
use App\Models\Book;
use Illuminate\Http\Request;
class BooksController extends Controller
{
public function index(Request $request)
{
// Recogemos los query params:
// i.get('/books', {params: { id}});
$id = $request->query('id');
// ... o los parámetros enviados en la url
// i.get(`/books/${id}`)
$id = $request->route('id');
if ($id!= null) {
$books = Book::where('categoryId', $categoryId)
->get();
return response()->json($books);
}
$books = Book::get();
// $books = Book::paginate(10);
return response()->json($books);
}
public function create(Request $request)
{
$title= $request->route('title');
$newBook = new Book;
$newBook->title= $title;
$newBook->save();
return response()->json(['message' => 'book created'], 200);
}
public function update(Request $request)
{
$title= $request->route('title');
$newBook = new Book;
$newBook->title= $title;
$newBook->save();
return response()->json(['message' => 'book updated'], 200);
}
public function destroy(Request $request, $digitalActionId)
{
$id = $request->route('id');
$res = Books::where('bookId','=', $id)->delete();
return response()->json(['message' => 'book deleted'], 200);
}
}
Componentes relacionados con la base de datos
Definiremos los datos de conexión el el fichero ./env
Migration
Creando la estructura de nuestras tablas
Siempre nombraremos nuestras tablas en plural. Esto es imprescindible para que todo funcione correctamente en Laravel. Las propiedades de las tablas podemos nombrarlas en singular.
Dentro de una migración, la función up() sirve para crear las columnas y la función down() para eliminar las columnas creadas. Este último paso nos permite revertir las migraciones.
Definiendo los tipos de dato
$table->string("title", 255);
$table->text("content");
$table->enum("posted", ["yes", "not"]);
$table->unsignedBiginteger('editorial_id')->unsigned();
$table->unsignedInteger('price')->unsigned();
Relación one to many
$table->foreignId("author_id")->constrained()->onDelete("cascade");
Esto relaciona la presente tabla con la tabla con el nombre en plural (authors) y busca su propiedad Id.
Relación many to many
Vamos a crear una relación muchos a muchos entre la tabla students y la tabla teachers. Para ello, ambas tablas deberán tener su correspondiente fichero de modelo y migración.
Necesitaremos una tabla auxiliar o de pivote. Para crear el modelo y su correspondiente fichero de migración de la tabla de pivote, podemos usar:
php artisan make:model StudentTeacher -m
Las instrucciones para crear el modelo y el fichero de migraciones por separado serían:
php artisan make:model StudentTeacher
php artisan make:migration create_student_teachers_table
En el fichero de migración de de student_teachers:
$table->unsignedBiginteger('student_id')->unsigned();
$table->unsignedBiginteger('teacher_id')->unsigned();
$table->foreign('student_id')->references('id')->on('students')->onDelete('cascade');
$table->foreign('teacher_id')->references('id')->on('teachers')->onDelete('cascade');
Para montar la base de datos borrando los datos anteriores y cargar los nuevos…
Seeder
./database/seeders/BrandSeeder.php
class BrandSeeder extends Seeder
{
/**
* Run the database seeds.
*/
public function run(): void
{
Book::create(
[
'title' => 'Viaje al centro de la tierra',
'title' => 'bla bla bla...'
]
);
}
}
./database/seeders/DatabaseSeeder.php
class DatabaseSeeder extends Seeder
{
/**
* Seed the application's database.
*/
public function run(): void
{
$this->call(BrandSeeder::class);
}
}
Para cargar los datos:
php artisan db:seed
Montar base de datos borrando datos
php artisan migrate:fresh --seed
- El modificador seed carga la base de datos con los datos especificados en los seeders.
- Es posible que en el gestor de la base de datos (heidi) no refresque los datos automáticamente y haya que cerrar la conexión y volver a abrirla para que se vean actualizados.
Consultas
Cuando necesito los datos de dos o más tablas puede pasar que:
- El where se aplica a todas las tablas que intervienen en la consulta → Usaremos join
Book::where('id', $bookId)
->join('autors', 'autors.bookId', '=', 'books.id')
- El where no se aplica a todas las tablas que intervienen en la consulta → Usaremos dos consultas
$books = $books1->concat($books2);
Añadiendo un alias.
->select('books.*', 'autors.name as autorName')
Recibiendo…
Un resultado:
$brand = Book::where('id', '=', $bookId)
->first();
Varios resultados:
$brands = Book::where('editorialId', '=', $editorialId)
->get();
Desplegar la aplicación en un servidor compartido
Navegaremos a la carpeta public de nuestro proyecto.
Logs
Debemos añadir la siguiente variable de entorno al fichero .env:
APP_DEBUG=true
Los logs aparecerán en storage/logs/laravel.logs.
Autentificación con Auth0
Instalaremos el módulo de auth0. Para ello, ejecutaremos el siguiente comando en la terminal:
composer require auth0/auth0-php
Añadiremos las siguientes variables de entorno al fichero .env:
# The URL of our Auth0 Tenant Domain.
# If we're using a Custom Domain, be sure to set this to that value instead.
AUTH0_DOMAIN='https://{yourDomain}'
# Our Auth0 application's Client ID.
AUTH0_CLIENT_ID='{yourClientId}'
# Our Auth0 application's Client Secret.
AUTH0_CLIENT_SECRET='{yourClientSecret}'
# Our Auth0 API's Identifier.
AUTH0_AUDIENCE='YOUR_API_IDENTIFIER'
Código de Laravel:
class UserController extends Controller
{
/**
* Display a listing of the resource.
*/
public function index(Request $request)
{
$token = $request->post('token');
$auth0 = new Auth0([
'domain' => env('AUTH0_DOMAIN'),
'clientId' => env('AUTH0_CLIENT_ID'),
'clientSecret' => env('AUTH0_CLIENT_SECRET'),
'audience' => [env('AUTH0_AUDIENCE')],
'cookieSecret' => env('AUTH0_COOKIE_SECRET'),
]);
$userInfo = $auth0->decode($token);
var_dump($userInfo);
}
La aplicación de React:
import { useAuth0 } from "@auth0/auth0-react";
const { loginWithRedirect, isAuthenticated, getIdTokenClaims } = useAuth0();
useEffect(() => {
if (isAuthenticated) {
getIdTokenClaims().then(({ __raw: idToken }) => login(idToken));
}
}, [isAuthenticated]);
Posible error al ejecutar una petición:
cookieSecret` must be configured
Uso del Middleware para gestionar la autentificación
php artisan make:middleware EnsureTokenIsValid
app\Http\Middleware\EnsureTokenIsValid.php
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Http\Request;
use Symfony\Component\HttpFoundation\Response;
use Auth0\SDK\Auth0;
use App\Models\User;
class EnsureTokenIsValid
{
private $auth0;
function __construct()
{
$auth0 = new Auth0([
'domain' => env('AUTH0_DOMAIN'),
'clientId' => env('AUTH0_CLIENT_ID'),
'clientSecret' => env('AUTH0_CLIENT_SECRET'),
'audience' => [env('AUTH0_AUDIENCE')],
'cookieSecret' => env('AUTH0_COOKIE_SECRET'),
]);
$this->auth0 = $auth0;
}
/**
* Handle an incoming request.
*
* @param \Closure(\Illuminate\Http\Request): (\Symfony\Component\HttpFoundation\Response) $next
*/
public function handle(Request $request, Closure $next): Response
{
$auth0 = $this->auth0;
$token = $request->header('Authorization');
$userInfo = $auth0->decode($token);
$userData = $userInfo->toArray();
$user = User::where('email', $userData['email'])->first();
if ($user == null) {
return response('Unauthenticated.', 401);
}
$request->request->add(['user' => $user]);
return $next($request, $user);
}
}
app\Http\Kernel.php
<?php
namespace App\Http;
use Illuminate\Foundation\Http\Kernel as HttpKernel;
class Kernel extends HttpKernel
{
protected $middleware = [
// ...
\App\Http\Middleware\EnsureTokenIsValid::class,
];
Para acceder al valor seteado en el middleware desde el controlador, usaremos:
$user = $request->get('user'); // Esto coge el dato que puse en el middleware