Documentos de Académico
Documentos de Profesional
Documentos de Cultura
Descripción breve
Este es un curso tomado del canal “CodersFree” de Youtube.
Se puede buscar como “Curso Laravel desde cero”
Curso de YouTube.
https://www.youtube.com/playlist?list=PLZ2ovOgdI-kWWS9aq8mfUDkJRfYib-SvF
Tabla de contenido
CAMBIAR ENTRE VERSIONES DE PHP (XAMPP)................................................................9
01 CREAR UN NUEVO PROYECTO EN LARAVEL...............................................................10
Método 1................................................................................................................................10
Método 2................................................................................................................................10
02. INSTALACIÓN DE EXTENSIONES...............................................................................10
Laravel Blade Formatter..........................................................................................................10
Php Inteliphese.......................................................................................................................11
Laravel Blade Snippets............................................................................................................11
Laravel Snippets......................................................................................................................11
Laravel goto view....................................................................................................................11
Spanish Languaje Pack for Visual Studio..................................................................................11
Tailwind CSS IntelliSense.........................................................................................................11
Alpine.js IntelliSense...............................................................................................................12
GitHub Copilot........................................................................................................................12
JSON Formatter.......................................................................................................................12
03.- Rutas en Laravel ¿Qué son y para que sirven?........................................................13
Definir una ruta.......................................................................................................................13
Definir una segunda ruta (URL )..............................................................................................14
Usar variables en las rutas.......................................................................................................14
Definir más de una variable en la ruta.....................................................................................15
04.- CONTROLADORES EN LARAVEL QUE SON Y PARA QUE SIRVEN...............................15
Crear el controlador................................................................................................................15
Asignar el control de una ruta a un controlador......................................................................16
Llamar controladores versión 8 Laravel....................................................................................................17
Definiendo controlador para la ruta raíz (página principal del proyecto)...........................................17
Definiendo controlador para rutas diferentes a la raíz del proyecto..................................................17
Llamar controladores versión 7 Laravel....................................................................................................19
13.- Ingresar varios registros de prueba a la base de datos sin usar “seeders” (factory).
.....................................................................................................................................48
Crear un archivo Factory.........................................................................................................49
Convención para la crear un archivo Factory...........................................................................................51
Definición de tipo de contenido para la Base de datos en el archivo Factory.........................................52
Métodos (Tipo de contenido) para faker..................................................................................................53
Ejecutar el factory...................................................................................................................55
14 - Realizar consultas a la base de datos con “eloquent”.............................................56
Métodos eloquent y su equivalencia en script........................................................................57
all()...................................................................................................................................................57
where(‘NombreColumna’, ‘operador’(opcional), ‘valorAFiltrar’)...................................................57
get().................................................................................................................................................58
Orderby(‘NombreColumna’, ‘valorAsc/Desc’)................................................................................58
first()................................................................................................................................................58
value(‘nombreColunma’)................................................................................................................58
find(valorID)....................................................................................................................................58
select(‘NombreColumna1’,’NombreColumna2-opcional’, ’NombreColumna3-opcional’, etc).....59
as.....................................................................................................................................................59
take(cantidad).................................................................................................................................59
15 – Mutadores y Accesores..........................................................................................59
Mutadores (set)......................................................................................................................59
Agregar Mutadores (Laravel 9.x)..............................................................................................................59
Agregar Mutadores (Laravel 8.x)..............................................................................................................61
Accesor (get)...........................................................................................................................61
Agregar Accesores (Laravel 9.x)................................................................................................................61
Agregar Accesores (Laravel 8.x)................................................................................................................62
Abreviatura al crear Mutadores, Accesores (laravel 9.x).........................................................63
Hacer test para probar los mutadores o Accesores.................................................................64
16 – Cómo listar y leer registros en Laravel...................................................................65
Recuperar datos de la base de datos y mostrarlo en un archivo HTML (view).........................65
Recuperar todos los datos de una tabla y mostrarlo en un archivo HTML (view)...................................65
Recuperar un solo registro (un solo campo) y mostrarlo con un determinado formato.........................65
Usar paginación para mostrar los registros que obtuvimos de la tabla...................................67
Poner botones con estilo CSS para desplazarse en la paginación de un archivo view............................68
Paginación con Tailwind.......................................................................................................................68
Paginación con Bootstrap....................................................................................................................69
Crear Alias para llamar a las rutas (URL)..................................................................................70
Crear una lista de con datos de una tabla y cada registro de esa lista sea un enlace el cual con
su ID nos redireccione a otro view para mostrar el campo nombre de ese ID.........................71
Codificación del archivo view Cursos (‘index.blade.php’)........................................................................71
Codificación del archivo controller Cursos (método show()....................................................................73
Codificación del archivo Vista final (show.blade.php)..............................................................................75
En las variables de entorno nos vamos en la segunda sección (variables del sistema) y
buscamos “path” para darle oble clic.
Método 1
Dependiendo donde se haya instalado XAMPP buscamos la carpeta “htdocs”.
Luego en línea de comandos (puede ser GIT Bash) nos situamos dentro de esa carpeta.
Y escribimos el comando la instrucción (en este ejemplo example-app es el nombre del
proyecto):
composer create-project laravel/laravel example-app
Método 2
Puede crear nuevos proyectos de Laravel instalando globalmente el instalador de Laravel a
través de composer.
Para ello vamos a la línea de comandos y escribimos la siguiente instrucción:
composer global require laravel/installer
(nota este comando se puede ejecutar en cualquier carpeta ya que tiene la palabra global)
Una vez instalador composer de manera global ahora cada que deseamos crear un nuevo
proyecto basta únicamente con realizar los siguientes pasos:
En la línea de comandos, situarnos en la carpeta donde queremos que se cree el proyecto.
Por ejemplo: /c/xampp/htdocs/
Luego escribir la siguiente instrucción (en este ejemplo example-app es el nombre del
proyecto):
laravel new example-app
Php Inteliphese
La que se utiliza es del autor Ben Mewburn
Tiene un icono de elefante. Esta extensión ahorra líneas de código de escritura. Me
permitirá que visual code autocomplete las líneas de código que necesito ahorrando
escribir líneas de código.
Por ejemplo, si sé que usaré el controlador CursoController, yo solo escribo “use” y el
nombre y esta extensión me escribe en automático todo el código necesario para usar
este controlador. Por ejemplo, escribo “use CursoController” y la extensión escribirá por
mi “use App\Http\Controllers\CursoController”
Laravel Snippets
Del autor Winnie Lin
Este es similar a Laravel Blade Snippets solo que nos proporciona ya para los archivos php
de Laravel. Por ejemplo para escribir rutas (route)
GitHub Copilot
Del Autor Github. Esta extensión se basa en inteligencia artificial. En la cual escribimos un
determinado código y dejando comentarios y en base a los comentarios que escribimos
nos va dando recomendaciones. Otras ocasiones se le va dando un nombre a una función
y en base a ese | nombre de la función te da una serie de recomendaciones o sugerencias
de código.
NOTA esta extensión es de paga (tiene un costo de 10 dolares mensuales)
JSON Formatter
Cuando por ejemplo traemos todos los registros de una tabla de la base de datos en
laravel (por ejemplo “NombreClaseModelo::all()” ) y la almacenamos en una variable y
posteriormente mostramos la información de la variable en una página web. El navegador
la muestra como una sola línea continua de todos los registros.
Esta extensión le dará un formato a la información para que no se muestre como línea
continua como se muestra a continuación:
03.- Rutas en Laravel ¿Qué son y para que sirven?
Al desarrollo en PHP por lo general se crea un archivo php por cada pagina que tenga la
aplicación web.
En Laravel tenemos un solo punto de entrada que es la carpeta public. Los usuarios que
interactúen con nuestra aplicación web solo podrán tener acceso a los archivos que están
dentro de esta carpeta. Po lo que los archivos de JavaScript u hojas de estilo (.css) aquí es
donde deben ir ubicados.
Cuando un usuario escribe una dirección web en especifico (una URL). Este URL pasa al
archivo web.php ubicado dentro de la carpeta “routes/web.php”. En este archivo es
donde definimos donde queremos que sea redirigido el usuario.
Cuando un usuario escriba una URL lo que hará Laravel es verificar si esa URL se ha
definido en el archivo web.php
El código anterior es que cuando el usuario escriba la ruta raíz de la aplicación (‘/’) esta se
redireccionara al un archivo blade llamado welcome.blade.php (ubicado en la carpeta
“resources/views/welcome.blade.php”)
Cuando una URL no se define en el archivo web.php y el usuario intenta ingresar, esto
genera un error “404 | Page not found”
De a modo de prueba podermos cambiar el método view (que mande a un archivo vista)
por un “string”
Route::get('/', function () {
//return view('welcome');
return "Bienvenido, estas en la página principal";
});
Esto lo que hace es que cuando se escriba la URL en el navegador imprimirá en pantalla
(en el navegador la etiqueta que se estableció)
IMPORTANTE: En caso de tener una segunda ruta o mas Laravel lee las rutas de arriba
hacia abajo por lo que si tienes dos URL similares, la acción que va a tomar será la primera
URL que encuentre y ahí de manera interna mete un break e interrumpe la búsqueda de
otra URL.
Para ello definimos una ruta como en la sección anterior (“definir una segunda ruta”)
Route::get('cursos', function(){
return "Bienvenido a la pagina cursos";
});
Para pasar una variable en la URL se define entre corchetes y también se la pasamos a la
función anonima entre paréntesis y dentro de la función en la cadena que regresamos la
imprimimos (de esta manera la impresión será dinámica de acuerdo al contenido que
traiga la variable)
Route::get('cursos/{curso}', function($curso){
return "Bienvenido al curso: $curso";
});
Nota: observe que la impresión de la variable esta dentro de las comillas del string.
Observe que donde se define la URL no necesariamente debe ser el mismo nombre que
recibe la función (en este ejemplo se define el nombre de la variable como {curso} y se
pasa a la función anónima como $id.
Variable Opcional.
Podemos definir que la variable sea opcional (tanto para la URL como para la función
anónima).
Esto se logra colocando un signo ? después del nombre de la variable en donde se define
la URL y en la función tenemos que definirle un valor (puede ser null). Como se muestra a
continuación
Route::get('cursos/{curso}/{categoria?}', function ($id, $categoria = null)
{
return "Bienvenido al curso: $id, de la categoria $categoria";
});
En este ejemplo, en la función anónima en automático su valor predeterminado de la
variable “$categoría” siempre será “null” hasta que le pasemos un valor a la variable
“categoría” del URL (donde se define el URL) 'cursos/{curso}/{categoria?}'
Con este ejemplo se puede manejar condicionales if para realizar una acción en caso que
la variable categoría de la URL tenga un valor o realizar otra acción en caso que no se haya
definido el valor de la variable categoría. Como se muestra en el siguiente ejemplo:
Route::get('cursos/{curso}/{categoria?}', function ($id, $categoria = null)
{
if ($categoria){
return "Bienvenido al curso: $id, de la categoria $categoria";
} else{
return "Bienvenido al curso: $id";
}
Cabe señalar que aunque se puede incrustar código php dentro de las rutas, las buenas
practicas dictan que tengamos separado el código php de las rutas. El código php viene
siendo la lógica que necesitamos por lo que se debe enviar a un archivo controlador. En
este archivo controlador es donde vamos a escribir toda la lógica de nuestra aplicación.
Crear el controlador
Este se crea desde la línea de comando
1. Verificar que estemos dentro de la carpeta del proyecto (por ejemplo c:\xampp\
htdocs\proyectocurso).
2. Escribimos el comando:
a. PHP artisan make:controller HomeController Home controller es
el nombre que queremos darle al controlador. Se recomienda poner un
nombre que identifique para que será el controlador.
b. La convención dicta que tiene que ser singular y posteriormente la palabra
Controller.
c. Puede escribirse en mayúsculas la primera letra de cada palabra sin
espacios.
Este comando me va a crear un archivo HomeController.php. Este archivo tiene código
php, dentro del archivo define un namespace que es donde se define la ruta de donde
están ubicados los controladores
namespace App/Http/Controllers;
También crea una clase con el nombre que le pusimos en este caso HomeController el cual
extiende las propiedades de la clase Controller.
Es dentro de esta clase donde se van a escribir los métodos que se encargarán de
administrar lo que definimos en web.php.
Route::get(‘ruta’, [nombrecontrolador::class);
Con ello de manera predeterminada Laravel en la clase del controlador buscara el método
__invoke() por lo que es importante resaltar que hay que definir un método __invoke()
cuando se omite el nombre del método en el comando “Route”.
Dentro del archivo web.php hay que especificar que vamos a usar ese controlador a través
del comando “use”
use App\Http\Controllers\HomeController;
Route::get(‘/’, HomeController::class);
Nota la función (doble guion bajo invoke “__invoke()”) es utilizada por default para definir
que es la raíz de la ruta (es cuando omitimos el nombre del método en el comando
“Route”.
Route::get('cursos', function(){
return "Bienvenido a la página Catálogo de cursos";
});
Route::get('cursos/create', function () {
return "Página de Formulario";
});
Podemos observar que tenemos la ruta “cursos” que se repite en los 3 Route. Por lo tanto,
puedo crear un solo controlador llamado CursoController y dentro de la definición de la
clase puedo ingresar las 3 funciones que será el llamado para cada uno de la clase
“Route”.
1. ‘curso’
2. ‘curso/create’
3. ‘curso/{id}’ este es una ruta (“curso”) que recibe una variable, lo que sea
después de curso de guardará en “id”.
El siguiente paso es crear el controlador:
1. Desde la línea de comando (ctrl + ñ en visual code) Escribimos el comando:
a. PHP artisan make:controller CursoController Curso controller es el
nombre que queremos darle al controlador. Se recomienda poner un
nombre que identifique para que será el controlador.
b. La convención dicta que tiene que ser singular y posteriormente la
palabra Controller.
c. Puede escribirse en mayúsculas la primera letra de cada palabra sin
espacios.
2. En el nuevo controlador creado (CursoController.php) dentro de la clase vamos a
crear 3 métodos (“index”, “create”, “show”) que será la conexión con la ruta de
Cursos.
3. class CursoController extends Controller
4. {
5. public function index(){
6. return "Bienvenido a la página Catálogo de cursos desde el
controlador";
7. }
8.
9. public function create(){
10. return "Página de Formulario desde el controlador";
11. }
12.
13. public function show($id){
14. return "Página curso de: $id desde el controlador";
15. }
16.}
17.
El método “index” será para la raíz del curso “/”, el método “créate” será para la
ruta “cursos/create” y el método show será para la ruta “cursos/$variable”.
Cabe señalar que por convección el nombre “index” es para la ruta raíz, “create” se
usa para definir formularios y “show” para mostrar algo.
19. Luego en este mismo archivo “web.php” se define la clase “Route” con la siguiente
sintaxis:
“Route::get(‘ruta’, [nombrecontrolador::class, ‘nombreMetodo’]);”.
El código sería:
Nota: hay que resaltar que “show” no pasa la variable “id”, no es necesario pasar la
variable al nombrar el método a usar (“show”) ya que aquí solo se indica el nombre del
método a usar, pero tanto en la definición del método (archivo “CursoController.php”)
como en la definición de la ruta (archivo web.php -comando Route) ahí se define que hay
una variable en la ruta y esta una función esperando el valor en la definición del método.
Route::get('cursos/{id}', [CursoController::class, 'show']); // archivo
web.php
$this->routes(function () {
Route::prefix('api')
->middleware('api')
->namespace($this->namespace)
->group(base_path('routes/api.php'));
Route::middleware('web')
->namespace($this->namespace)
->group(base_path('routes/web.php'));
});
}
El código sería:
Route::controller(CursoController::class)->group(function(){
Route::get('cursos', 'index');
Route::get('cursos/create', 'create');
Route::get('cursos/{id}', 'show');
});
En este código se define la clase Route el cual hace referencia al método controller.
Dentro del método controller() se va a definir el controlador a usar (sin comillas).
El operador -> hace referencia al método group del objeto Route. Dentro del método
group() se define una función anónima el cual va a contener (se agruparán) todas las rutas
que utilizarán este controlador
Creación de vistas
Se crean las páginas web o archivos “php” que serán las vistas (este se crea directamente
en la carpeta del proyecto). Por ejemplo, para la página web principal del proyecto se
crear el archivo home.php y se inicializa con la estructura de un código HTML. En caso de
que la clase “Route” (archivo “web.php”) comparta una misma ruta (por ejemplo “cursos”
se puede crear la carpeta cursos y dentro de esta carpeta se crearían las pagina web por
cada una de las rutas)
return view('home');
NOTA: al pasarlo como parámetro dentro del método “view()” no se necesita poner la
extensión del archivo (se omite “.php”).
return view('cursos.create');
Route::get('cursos/{id}', 'show');
En el archivo controlador que recibe la variable del “web.php”. la variable tiene que
recibirse como parámetro en 2 métodos.
El método “show()” recibe la variable como parámetro y el método “view()”. En el método
“view()” esta variable se pasará como segundo parámetro (en el primer parámetro se pasa
la ruta del archivo).
Cabe señalar que el segundo parámetro que se pasa al método view pasará dentro de
corchetes. El método View tendrá la siguiente sintaxis
Abreviatura para pasar una variable como parámetro al método View compact()
En el archivo controlador que necesita recibir una variable; en el segundo parámetro,
cuando se utiliza la misma etiqueta tanto en la variable que se le pasara al HTML como la
variable que recibe la información, por ejemplo:
view(‘ruta’, [‘nombreCualquiera’ => $ nombreCualquiera]);
//Código Simplificado
return view ('cursos.show', compact('id'));
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title> @yield('tittle') </title>
</head>
<body>
@yield('content');
</body>
</html>
4. Ya en los archivos vista que usaran la plantilla base (por ejemplo “home.php”), en
vez de usar le código HTML completo solo haremos referencia a las áreas
dinámicas de la plantilla base. Para ello es necesario:
a. Se renombra el archivo vista “home.php” anexándole la extensión “.blade”
quedando de la siguiente manera “home.blade.php”
b. Todas las instrucciones no terminan en punto y coma
c. La primera línea de código es ingresar una extensión con la ruta donde
está ubicada la plantilla @extends(‘rutaPlantilla’). En nuestro ejemplo la
plantilla base “plantilla.blade.php” esta dentro de la carpeta “layouts”.
@extends('layouts.plantilla')
Usando blade para sustituir echo php dentro de HTML por {{}}
En vez de imprimir un echo dentro del código HTML podemos simplificar esta instrucción
con dobles lleves como se muestra a continuación
Esta instrucción quiere decir que a ‘default’ se le asigna un valor, ya sea del primer
parámetro que tiene el método env(‘parametros1’,’parametro2’) y en caso de no
encontrarlo se le asigna el valor del segundo parámetro. El cual tiene el valor explicito
‘mysql’.
El primer parámetro son las variables definidas dentro del archivo “.env”. En este ejemplo
‘DB_CONNECTION’.
NOTA: El archivo “.env” se preconfigura con los datos del proyecto, como por ejemplo el
nombre de la base de datos, sin embargo en caso de usar un nombre de base de datos
diferente hay que tener en cuenta que se debe configurar.
Estas con las variables que vienen en el archivo “.env” y su configuración par aun proyecto
Laravel llamado “salón”
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=salon
DB_USERNAME=root
DB_PASSWORD=
Estructura de un archivo
Un archivo create_users_tabla.php tiene una clase CreateUsersTable que se extiende de la
clase Migration.
Esta clase tiene 2 metodos: le método up() y le método down().
el objeto $table se utiliza para crear cada una de las columnas de nuestra tabla
$table->string(‘email’)->unique();
$table->string(‘email2’)->nullable();
$table->timestamps();
“dropIfExists(‘nombreTabla?);
Este método eliminara la tabla creada por el método “créate”. Nota eliminará la tabla
creada por el método create que este dentro de su mismo archivo migrate.
Eliminar todas las tables de la base de datos y volverlas a crear en línea de comando.
Si necesitamos eliminar todas las tablas que tenemos en el sistema y volverlas a crear.
Tenemos 2 instrucciones que podemos usar:
1. php artisan migrate:fresh // este no utiliza el método “down()” para eliminar las
tablas
2. php artisan migrate:refresh //este utiliza el método “down()” para eliminar las
tablas
La instrucción 1 lo que hace es eliminar todas las tablas (sin leer el método “down()”) y
luego ejecuta el método “up()” de cada una de los archivos migrate. En otras palabras,
elimina las tablas sin usar el método down() por lo que de un solo “golpe” elimina todas
las tablas de esa base de datos para después ejecutar uno a uno el método up() de los
archivos migrate que estén en la carpeta “database/migrate”. Esta instrucción garantiza
que se eliminaran las tablas ya que al no usar el método down elimina la posibilidad que el
método este mal escrito y por ende no pueda borrarse la tabla.
La instrucción 2 lo que hace es recorrer la tabla migrations de la base de datos y todas las
migraciones que estén registradas en esta tabla ejecuta su método “dropifExits()” sin
importar su número de lote (elimina cada una de las tablas), a continuación ejecuta el
método “up()” (crea cada una de las tablas). En otras palabras elimina las tablas usando el
método “down()” de todas las migraciones registradas en la tabla “migrations” primero
ejecuta el método “down()” y posteriormente ejecuta el método “up()”.
Con esta instrucción todos los registros de la tabla “migrate” tendrán lote 1 ya que lo que
hace es vaciar la tabla y posteriormente ejecuta el método “up()” con todas las
migraciones que encuentra en la carpeta “database/migrations”, ejecutándolas todas
como un mismo lote, en este caso lote 1.
Este método lo que hace es un rollingback (ejecutar el método “down()”) de todas las
migraciones pero no realiza el método “up()” de estas migraciones. Con ello en la base de
datos solo dejaría la tabla de migraciones.
Ejecutar una migración (ejecución del método “up()”)
Para ejecutar una migración se va a línea de comandos (por ejemplo, de visual Code
presionando control + ñ) y escribimos el siguiente comando
Nota: si hace una modificación (por ejemplo, agregar más columnas, cambiar nombre,
etc.) es importante primero guardar el archivo antes de ejecutar la instrucción, de lo
contrario únicamente ejecutara lo que se haya guardado en el archivo.
Este comando recorrerá y ejecutara únicamente el método “up()” de cada uno de los
archivos migrate (de ese mismo lote) que tengamos dentro de la carpeta
/database/migrate.
Este comando recorrerá y ejecutara únicamente el método “down()” de cada uno de los
archivos migrate (de ese mismo lote) que tengamos dentro de la carpeta
/database/migrate.
Lotes de migración.
Los lotes se manejan para el control de versiones, todos aquellos registros (archivos
migrate) que compartan el mismo bloque son los que se ejecutaran simultáneamente, ya
sea el consecutivo para registrar la ejecución de una migración o el consecutivo anterior
para deshacer la tarea realizada.
¿Que es un lote?
Dentro de las tablas que se crean por default en la base de datos esta la tabla “migrate”
(esto en base de datos). Esta tabla lleva un control de los archivos migrate que ya se
ejecutaron poniéndoles una bandera de valor 1 (esto por ser la primera ejecución – primer
lote- de la instrucción php artisan migrate + enter) y con ello ya tiene un control sobre los
archivos que se ejecutaron, de esta manera se manejan Lotes.
Cada migración se maneja en bloque (lote)s, es decir cada que ejecutamos la instrucción
“php artisan migrate + enter” busca todos los nuevos archivos existentes en la carpeta
“/database/migrate” y los ejecuta como un segundo lote, poniéndole un numero 2 a la
segunda ejecución y si se vuelve a ejecutar la instrucción buscaría nuevos archivos de
migración y ejecutaría todos los nuevos archivos que encuentre y a estos archivos les
pondría lote 3 y así sucesivamente.
Esto sirve para el control de versiones ya que cada que queramos revertir una actividad,
esta se revertiría por aquellas migraciones que tengan el mismo número de lote es decir
primero se revierte todas las migraciones que tengan el lote 3, luego todos los que tengan
lote 2 y posteriormente los que tengan lote 1.
Nota. Si revierto una actividad por ejemplo el lote 3 y posteriormente vuelvo a revertir la
actividad del lote 2, dejando solamente las migraciones del lote 1. Al volver a realizar la
actividad (ejecutar la migración) este nuevo lote tendrá el numero 2 pero contendrá los
archivos del lote 3 y 2 revertidos anteriormente. Esto porque las migraciones que se
revirtieron quedaron “listas” para volver a ejecutarse y recuerda que la ejecución de la
migración se hace por todos los archivos que estén listos para migrarse.
El punto 1 nos crea el archivo de migración únicamente con los métodos up y down
vacíos.
class Ejemplo extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
//
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
//
}
}
Mientras que el punto 2 nos crea los métodos up y down y dentro sus respectivos
métodos (método “créate()” para el método “up()” y “dropIfExists()” para el método
“down()”). En otras palabras, respetando la convención nos ahorra líneas de código. Esto
es posible ya que en el nombre le estamos pasando create y por ende identifica que
queremos crear una tabla.
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('ejemplo2');
}
}
Por cada modificación se recomienda crear un archivo migrate a fin de tener un mejor
control. La convención dicta que debe ser lo más descriptivo posibles (en este ejemplo,
agregar una nueva columna) to_nombreColumna_table es la parte importante
en el ejemplo usaremos:
php artisan make:migration add_ColumnaTipo_to_cursos_table + enter
En la instrucción:
$table->string('tipo')->nullable()->after('descripcion')
El método “nullable()” permite que la columna acepte valores nulos. Con
parámetro false se establece que no permite valores nulos.
El método “after(‘nombreColumna)” permite agregar la columna después de la
columna que manifestamos dentro del método after.
->default($value) permite ingresar un valor predeterminado cada que se
agregue un registro.
Dentro del método “down()” hay que meter el código que revierta este proceso.
El método utilizado para eliminar columnas es “dropcolumns(‘nombrecolumna’)”
public function down()
{
Schema::table('cursos', function (Blueprint $table) {
$table->dropColumn('tipo');
});
}
Modificar las propiedades de una columna
Según la documentación de laravel antes de modificar una columna, se debe instalar el
paquete “doctrine/dbal”. La doctrina DBAL library es usada para determinar el estado
actual de la columna y a crear los queries SQL necesarios para realizar los cambios
solicitados en las columnas. Esta instalación es por cada proyecto Laravel.
en el ejemplo sería:
php artisan make:migration cambiar_propiedades_to_cursos_table + enter
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::table('cursos', function (Blueprint $table) {
//
});
}
}
Change() es el método dentro del método “up()” que realice los cambios de propiedad de
la columna. En este caso se configura la columna para aceptar como máximo de 50
caracteres y acepte registros nulos.
Schema::table('cursos', function (Blueprint $table) {
$table->string('nombre',50)->nullable()->change();
});
Creación de modelos
La ruta donde se almacenan los archivos modelos es “app/models”.
La lógica para la inserción de registro o modificación de registros en una tabla de base de
datos se realiza dentro de los modelos (modelo, vista, controlador) por lo que tenemos
que crear un modelo para cada tabla.
Si se usa la convención para crear el modelo, el nombre debería de ser el singular (en
inglés) del nombre que tiene la tabla en la base de datos. Por ejemplo, si la tabla en la
base de datos se llama categories se puede crear el modelo usando:
puede crear diferentes tipos de clases (archivos) al momento de crear el modelo, como
pueden ser factory, seeder, migration, controllers, etc. Estas opciones pueden combinarse
para crear múltiples tipos de clases de manera simultanea
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
3. Crea una instancia de la clase y asignarla a una variable con el siguiente código
$curso = new curso;
5. Se asignan todos los demás valores que deseamos ingresar a la tabla de acuerdo
con su propiedad (columna en la tabla de la db) correspondiente. Por ejemplo
$curso->descripción=”framework de php” + enter. // “framework de php” se
guardará en la columna cursos de la tabla Cursos en la base de datos.
Revisar el contenido a guardar en la tabla de base de datos
Antes de mandar a guardar toda la información es recomendable revisar toda la
información que hemos asignado a la variable.
Para ello es suficiente con solo escribir el nombre de la variable:
$curso; + enter
Este nos mostrara todo el contenido que tiene almacenada esta variable (contenido que
nosotros fuimos asignando a la instancia de la clase)
Guardar la información en la tabla de la base de datos
Si todo esta correcto podemos guardar a guardar la información en la tabla de la base de
datos con la propiedad save(). Con la siguiente instrucción se manda a guardar la
información que contiene la variable de la instancia a la tabla de la base de datos.
$curso->save();
Esto lo que hará es que de manera automática se a completará la información de los otros
campos faltantes de la tabla como id, created_at, update_at). Por lo que si volvemos a
revisar el contenido de la variable $curso; este ahora trae toda la información que se
guardó en la tabla de la base de datos y posteriormente se le asigno esta la variable
$curso.
En el primer ejemplo podemos ver que la variable $curso; solo tiene asignado las
propiedades nombre, descripción y tipo.
Posteriormente guardamos la información en la tabla de la base de ($curso->save();).
Al revisar nuevamente la variable $curso; ahora podemos notar que tiene asignadas mas
propiedades como id, update_at y créate_at). Esto es por que la información ya se guardo
en la tabla de la base de datos y al mismo tiempo actualizo la información que se asignó
en la variable $curso
Seeders
Estos datos creados por factory se van a ejecutar desde otra estructura conocida como
seeders
<?php
namespace Database\Seeders;
<?php
namespace Database\Seeders;
use Illuminate\Database\Seeder;
En este archivo hay que definir qué modelo vamos a usar y posteriormente dentro del
método “run()”, definir una instancia de la clase para almacenar los datos que se enviaran
a la base de datos
<?php
namespace Database\Seeders;
use Illuminate\Database\Seeder;
use app\Models\curso; //definimos el modelo a usar
}
}
$this->call(CursoSeeder::class);
namespace Database\Seeders;
use App\Models\curso;
use Illuminate\Database\Seeder;
namespace Database\Factories;
use Illuminate\Database\Eloquent\Factories\Factory;
Importante: Debido a que los modelos van muy ligados a los factory o seeder (sin un
modelo en factory o Seeder no pudiera funcionar). Se recomienda que al momento de
crear un modelo se cree igualmente el factory (con el fin que ese modelo se enlace de una
vez con ese factory). Esto se logra en línea de comando con la siguiente instrucción (como
ejemplo crearemos el modelo “Curso”)
php artisan make:model Curso -f
2. (versión 7 de Laravel)
php artisan make:factory NombreModeloFactory - - model=NombreClaseModelo +
enter (ejemplo “php artisan make:factory CursoFactory - - model=Curso” + enter)
o En este código al momento de crear un archivo factory por default define
de una vez el modelo a utilizar y las líneas de Código necesarias para
enlazarlo al modelo)
o En la versión 7 o anterior de Laravel si no se usaba la opción –
modelo:NombreClaseModelo creaba un archivo genérico y posteriormente
habría que ingresar el código necesario para enlazar el factory con su
respectivo modelo.
El archivo austero creado por factory quedaría de la siguiente manera:
3. <?php
4.
5. namespace Database\Factories;
6.
7. use Illuminate\Database\Eloquent\Factories\Factory;
8.
9. class CursoFactory extends Factory
10.{
11. /**
12. * Define the model's default state.
13. *
14. * @return array
15. */
16. public function definition()
17. {
18. return [
19. //
20. ];
21. }
22.}
23.
El archivo ya definiendo el modelo a utilizar.
24.<?php
25.
26.namespace Database\Factories;
27.
28.use Illuminate\Database\Eloquent\Factories\Factory;
29.use app\Models\curso; //se agregó esta definición
30.
31.class CursoFactory extends Factory
32.{
33. /**
34. * Define the model's default state.
35. *
36. * @return array
37. */
38. protected $model = curso::class; //se agregó esta definición
39. public function definition()
40. {
41. return [
42. //
43. ];
44. }
45.}
namespace Database\Factories;
use App\Models\People; //se tiene que agregar que vamos a usar este modelo
use Illuminate\Database\Eloquent\Factories\Factory;
Para generar los datos aleatorios Laravel hace uso de la librería “Faker” de PHP.
1. Se definen los campos que tiene la tabla y quedemos ingresar información. Nota: si
desea omitir un campo debe tener cuidado que ese campo en específico permita
valores nulos.
‘nombre’,
‘direccion’
2. La clase CursoFactory se extiende de una clase base llamada “Factory”, por lo
tanto:
a. Ponemos la palabra $this (para hacer uso de los métodos de la clase -en
este caso como la clase extiende los métodos de la clase base es igual a que
clase llame) y luego decimos que vamos a usar el método faker
‘nombre’=>$this->faker
'nombre' =>$this->faker->name(),
sentence() – Genera una oración (con punto final) por default son 6 palabras.
Opcionalmente se puede proporcionar un segundo parámetro booleano. Cuando
es “false”, solo se generarán oraciones con la cantidad que se le definió. Por
defecto “sentence” podría desviarse de la cantidad definida en un +/-40%.
faker->sentence();
// 'Sit vitae voluptas sint non voluptates.'
faker->sentence(3);
echo $faker->paragraph(2);
// 'Consequatur velit incidunt ipsam eius beatae. Est omnis autem illum iure.'
// 'Laborum unde mollitia distinctio nam nihil. Quo expedita et exercitationem voluptas
impedit.'
echo $faker->safeEmail();
// 'spencer.ricardo@example.com', 'wolf.sabryna@example.org'
unique().- Va en conjunto con otro método (como por ejemplo “safeEmail()”) y
este se encarga que siempre regrese un valor único (que no se repita), si pasamos
un valor true en su parámetro ($reset=true) entonces se pueden repetir los
valores.
// unique() forces providers to return unique values
$values = [];
for ($i = 0; $i < 10; $i++) {
// get a random digit, but always a new one, to avoid duplicates
$values []= $faker->unique()->randomDigit();
}
print_r($values); // [4, 1, 8, 5, 0, 2, 6, 9, 7, 3]
// you can reset the unique modifier for all providers by passing true
as first argument
$faker->unique($reset = true)->randomDigitNotNull(); // will not throw
OverflowException since unique() was reset
// tip: unique() keeps one array of values per provider
Esta es la página web se encuentran todos los métodos para faker y su explicación.
https://fakerphp.github.io/
Ejecutar el factory
Existen 2 formas de ejecutar un factory.
1. Esta puede ser desde un archivo seeder que no sea el principal
“DatabaseSeeder.php”. Esta es la manera como ejecutar un factory desde
cualquier archivo seeder.
a. Dentro del archivo seed que queremos utilizar, escribimos el siguiente
código dentro del método “run()”.
Debemos declarar use y la ruta de la clase a usar
NombreClaseModelo::factory(cantidad->create();
Por ejemplo:
use app\Models\curso;
2. Este es la formar que Laravel recomienda para ejecutar el archivo Factory. Debido
a que el archivo principal de los seeder es el archivo “DatabaseSeeder.php”
podemos agrupar desde este archivo todas las llamadas de los factory a ejecutar y
con ello evitar la creación de archivos seeder por cada tabla y así evitar llenarnos
de archivos. Es desde este archivo dentro del método “run()” donde se escribe la
instrucción para ejecutar el factory.
use app\Models\curso;
Para poder realizar pruebas podemos utilizar en línea de comandos “Tinker” (en secciones
anteriores se explica como instalarlo y su uso - capitulo 11 -).
1. Ingresar a “Tinker”, en línea de comando escribimos “php artisan tinker”
2. Indicamos que vamos a utilizar el modelo use App\Models\Curso; (de preferencia
respetar las mayúsculas como lo tenemos en el directorio del proyecto).
3. Se llama al modelo (en este ejemplo es “curso”) se pone el método equivalente al
script que queremos ejecutar y para poder utilizar la información debemos
almacenarla en una variable (en este ejemplo “$curso”) $curso = Curso::all();
Nota: Recuerde que estos métodos se puede combinar para poder hacer una consulta
mas “robusta”. Por ejemplo orderby()->all();
all() – recupera toda la información que tiene la tabla y lo guarda en una variable
en forma de arreglo, ha colocado cada fila de la tabla en su respectivo índice del
arreglo como si fuera un objeto. Es decir, una fila completa (con todos sus
campos) de la tabla de la base de datos se guardará en el índice 1, la segunda fila
(completa con todos sus campos) de la tabla de la base de datos se guardará en el
índice 2. Para poder acceder a cada campo de la fila y poner estos campos (por
ejemplo, el campo “nombre”) en una tabla o formulario HTML tendríamos que
usar un “foreach” para recorrer uno a uno cada registro y obtener la información
de cada campo (por ejemplo, el campo nombre).
Este método por sí solo NO regresa una colección de objetos como el método
“all()”. Por lo que no podríamos usarlo, para que esta información que regresa el
método where puede ser almacenada como un arreglo de objetos debemos
ponerle el método get(). “$variable = NombreClaseModelo::where(‘nivel’,
’universidad)->get();”
find(valorID) – recupera una fila con su valor de id, esto seria lo mismo que
escribir “where(‘id’,5)->first();” por ejemplo.
$curso = Curso::find(5);
select(‘NombreColumna1’,’NombreColumna2-opcional’, ’NombreColumna3-
opcional’, etc) – este método nos permite regresar únicamente el valor de la
columna que especificamos. Va acompañado del método “get()” o “first()” para
poder obtener un arreglo (colección de objetos)
$curso = Curso::select(‘nombre’,‘nivel’,’descripcion’)->orderby(‘id’,’asc’)->get();
as - alias para las columna, en el parámetro del select aquella columna que
queremos cambiar su etiqueta por un alias se usa el comando as. Por ejemplo, el
campo “nombre” quiero que ahora se llame “título”. Esto regresa la colección solo
que la propiedad (columna) “nombre” ahora será la propiedad “titulo”.
$curso = Curso::select(‘nombre as titulo’)->get();
15 – Mutadores y Accesores
Los mutadores permiten tomar datos (por ejemplo, de un formulario) e
independientemente de cómo se encuentren (por ejemplo: “EjemPlo”, “EJEMplo”,
“eJEMplo”, etc.) Los mutadores lo convierten en minúsculas y así es como lo almacenaran
en la base de datos.
Estos mutadores se colocan dentro de los modelos encargados de almacenar la
información dentro de nuestra tabla de la base de datos.
Mutadores (set)
Los mutadores usan el comando “set” ya que lo que hace es convertir el dato antes de
guardarlo en la base de datos. Es decir, Los mutadores transforman el valor antes de
almacenarlo en la base de datos.
1. Toma o recibe la información, ya sea de un formulario, o directo de la base de
datos.
2. la convierte según lo solicitado, por ejemplo, todo lo convierte en minúsculas.
3. ya convertida la información, la guarda en la base de datos
“use Illuminate\Database\Eloquent\Cast\Attribute;”
2. Dentro de la clase del modelo, creamos un método que este protegido (protected)
que llevará por nombre el nombre de la propiedad(campo) que deseamos
modificar (por ejemplo, el campo ‘name’). Este método nos retornara una nueva
instancia de la clase “Attribute” (recuerden que la definición la declaramos en el
punto anterior). Este método nos va a regresar un “Attribute” (“protected function
name(): Attribute”)
protected function name():Attribute
{
return new Attribute();
}
Nota: para afectar a varios registros solo cambiamos el nombre de la variable $value por
$value1. El $value afecta al primer registro y el $value1 afecta al segundo registro y así
consecutivamente.
}
Accesor (get)
Estos permiten recuperar la información de la base de datos, a diferencia del mutador,
este no cambia la información de la base de datos, es decir mutador si cambia la
información que se guardara en la base de datos y el Accesor solo obtiene la información
de la base de datos, la transforma para mostrar al usuario, pero no almacena ese en la
base de datos. Es decir, Los Accesores no modifican los valores en la base de datos,
simplemente transforman como se lo presentan al usuario.
4. Dentro de la clase del modelo, creamos un método que este protegido (protected)
que llevará por nombre el nombre de la propiedad (campo) que deseamos
modificar (por ejemplo, el campo ‘name’). Este método nos retornara una nueva
instancia de la clase “Attribute” (recuerden que la definición la declaramos en el
punto anterior). Este método nos va a regresar un “Attribute” (“protected function
name(): Attribute”)
protected function name():Attribute
{
return new Attribute();
}
Es exactamente lo mismo que el siguiente código (usando el operador flecha de php) solo
que es menos escritura de código.
protected function name(): Attribute
{
return new Attribute(
get: fn($value) => strtolower($value),
(usuario escribe dirección web) URL -> web.php -> ArchivoController -> archivoView
Dado que el archivo controlador es el que indica que archivo view (HTML) es el que se va a
desplegar, este archivo controlador es el que recibe los datos que le envía el archivo
modelo. Es decir, el archivo modelo es el encargado de recibir la información de la base de
datos y este se lo pasa al controlador para que finalmente se lo pasen a la vista.
(usuario escribe dirección web) URL -> web.php -> ArchivoController -> ArchivoModelo-
>ArchivoController->archivoView
Recuperar todos los datos de una tabla y mostrarlo en un archivo HTML (view).
Traer todos los archivos de una tabla de una base de datos puede traer problemas si esta
tabla tuviera por ejemplo más 1000 registros. Más adelante explicaremos como usar la
paginación en un archivo view.
Lo primero es: en el archivo controlador definimos el modelo que administra la tabla en la
base de datos de la siguiente manera:
1. Declarando que se usara ese modelo
“use App\Models\curso”
2. En una variable (por ejemplo $curso1), guardamos lo que traiga el modelo con el
método “all()".
$curso1 = curso::all(); //el método all() trae todos los registros de la tabla que apunte el
modelo, en este caso la clase modelo llamada “curso”.
3. Podemos ver el contenido de la variable con un “return $curso1;”.
Recuperar un solo registro (un solo campo) y mostrarlo con un determinado formato
En el punto anterior todo el registro de una tabla de la base de datos la guardamos en una
variable “$curso1”. Para darle un formato a ese registro hay que pasar la variable
“$curso1” a la vista.
en el archivo controlador definimos el modelo que administra la tabla en la base de datos
de la siguiente manera:
1. Declarando que se usara ese modelo
“use App\Models\curso”
2. En una variable (por ejemplo $curso1), guardamos lo que traiga el modelo con el
método “all()".
$curso1 = curso::all(); // el método all() trae todos los registros de la tabla que apunte el
modelo, en este caso la clase modelo llamada “curso”.
3. Podemos ver el contenido de la variable con un “return $curso1;”.
4. Recuerde que para pasar una variable a un archivo view usamos el método
compact(‘variable’), recuerde que esto es equivalente a:
‘NombreCurso’ = “$NombreCurso”
Nota: En el archivo vista si solo imprimimos $item, este imprimirá todo el registro (toda la
fila de la tabla). Para imprimir solo el valor que tiene esa columna usamos $item-
>nombreColumna (en este ejemplo el nombre de la columna es ‘nombre’).
http://localhost/salon/public/cursos?page=2
@section('content')
<h1>Página Catálogo de cursos desde el view usando Blade</h1>
<ul>
@foreach ($curso1 as $item)
<li>{{ $item }}</li>
@endforeach
</ul>
Poner botones con estilo CSS para desplazarse en la paginación de un archivo view.
Paginación con Tailwind
Tailwind es un framework CSS como lo es Bootstrap. La diferencia es que Bootstrap es una
tanto más difícil de personalizar sus componentes y esto se debe a que la mayoría de los
estilos CSS de Bootstrap tiene la propiedad “important” y esto hace que muchas veces no
permita personalizar sus componentes.
Tailwind CSS lo que quiere es que tú crees tus propios componentes. Es decir, Tailwind nos
brinda estilos que nosotros podemos combinar para crear nuestros propios componentes.
Podemos dar un estilo al botón. Para esto, este curso se basa en estilos Tailwind.
Dado que estas clases de Tailwind se aplicarán para todas las páginas, entonces en la
plantilla base es donde colocaremos el código (librería) que le dará estilo a los botones.
Nota: Recuerde que para insertar código PHP dentro de HTML se puede usar:
a. Código HTML <?php route(‘nombreAlias’)" ?> Código HTML
a. Código HTML {{route(‘nombreAlias’)}} Código HTML… este último es una facilidad
que nos da Blade.
Laravel recomienda que apuntemos a las rutas de esta manera principalmente por dos
razones
1. Por mantenimiento del código, ya que si cambiamos físicamente la URL del archivo
vista (por ejemplo, lo cambiamos de carpeta o de nombre) el alias sigue apuntando
a ese path URL y por lo tanto no tendríamos que actualizar el código donde se hizo
referencia a esa URL.
2. Por seguridad. Esto es cuando usamos controladores para redirigir el URL, ya que
al crear un alias podemos esconder la ruta (path) real de nuestro archivo vista. Es
decir, al escribir el URL que tiene el alias, este nos redireccionara a la vista, pero la
dirección del navegador mostrar como link el alias y no el directorio real.
Es decir, de este código donde tenemos definido el URL real “cursos/ejemplo”
Route::get('cursos/ejemplo', [CursoController::class, 'ejemplo'])-
>name('URLEscondido');
Al usar el alias podríamos esconder el URL. En vez de que el usuario escriba la ruta real
“cursos/ejemplo” podrá escribir “http://localhost/salon/public/e” y accedería a la misma
página solo que el URL está escondido.
Route::get('e', [CursoController::class, 'ejemplo'])->name('URLEscondido');
Como podrán ver aquí el método “ejemplo()” es el que regresa el método “view()” con la
ruta real (URL) del archivo vista.
Crear una lista de con datos de una tabla y cada registro de esa lista sea un enlace el
cual con su ID nos redireccione a otro view para mostrar el campo nombre de ese
ID.
Para esta tarea se van a trabajar 3 archivos
1. El archivo view Cursos (‘index.blade.php’). El cuál es el archivo vista que desplegara
el “catalogo cursos” por la columna nombre.
2. El archivo controlador el cuál a través de su método correspondiente (en este
ejemplo “show()”) traerá toda la información de la base de datos para después
pasarla al archivo vista final (‘cursos\show’).
3. El archivo view final (‘cursos\show’) que recibirá la variable del controlador que
tiene los registros de la tabla de la base de datos y los mostrara al usuario final.
2. Ponemos como enlace (dentro del “href”) el alias del view. Esto se logra con el
método “route(‘alias’, ‘parámetro-opcional-’ )”.
<ul>
@foreach ($curso1 as $item)
<li>
<a href="{{route('cursos.show',$item->id)}}">{{ $item->nombre
}}</a>
</li>
@endforeach
</ul>
Para el texto del tag <a href=””> estamos imprimiendo la columna nombre de la
base de datos con la propiedad ”$item->nombre”.
El archivo completo del archivo index.blade.php
@extends('layouts.plantilla')
@section('content')
<h1>Bienvenido a la página Catálogo de cursos desde el view usando
blade</h1>
<br>
<ul>
@foreach ($curso1 as $item)
<li>
<a href="{{route('cursos.show',$item->id)}}">{{ $item->nombre
}}</a>
</li>
@endforeach
</ul>
@endsection
Codificación del archivo controller Cursos (método show().
En el archivo controlador, buscamos el método que tiene como destino archivo view final
(en este caso archivo (‘show.blade.php’).
Dentro de este método (método “show()”) codificamos 2 puntos:
1. Obtenemos los registros de la base de datos y lo guardamos en la variable
“$curso”. En este ejemplo Utilizamos el método “find()” para obtener los registros
de la base de datos. Este método pasa el id del registro y recupera los demás
registros faltantes de ese id. Recuerde que en la página catálogo de cursos (archivo
‘index.blade.php’) en el link de cada lista pasamos el ID del registro y este id es el
que pasamos como variable en clase Route::get() del archivo web.
$curso = curso::find($id);
namespace App\Http\Controllers;
use App\Models\curso;
use App\Models\Maestro;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\URL;
use Illuminate\Support\Str;
$curso1 = curso::paginate();
return view('cursos.index', compact('curso1'));
}
}
Codificación del archivo Vista final (show.blade.php)
Este archivo es el que desplegara al usuario el nombre del curso de acuerdo al id
obtenido.
1. En el archivo vista Blade final (en este caso ‘cursos/show’), dentro de “@section”
vamos imprimir en el HTML el nombre
<h1>Bienvenido al curso "{{$curso->nombre}}" desde el view usando blade</h1>
@section('content')
@if (is_string($curso)) {{-- Se usa if para busca si la variable es un
registro (colección de la base de datos) o solo una cadena (string)--}}
<h1>Bienvenido al curso "{{$curso}}" desde el view usando blade</h1> {{-- Si
es una cadena se imprime la cadena --}}
@else
<h1>Bienvenido al curso "{{$curso->nombre}}" desde el view usando blade</h1>
{{-- si es un registro se imprime su propiedad --}}
@endif
@extends('layouts.plantilla')
@section('content')
<h1>Página de Formulario desde el view usando blade</h1>
<form action="" method="post">
<label>
Nombre:
<br>
<input type="text" name="name">
</label>
<br>
<label>
Descripcion :
<br>
<textarea name="descripcion" rows="5">
</textarea>
</label>
<br>
<label>Categoria
<br>
<input type="text" name="categoria">
</label>
<br>
<br>
<button type="submit"> Ingresar registros</button>
</form>
@endsection
Luego que el usuario llene los campos del formulario esta información se tiene que enviar
a algún lado para que se procese. En la propiedad “action” del “form” es donde indicamos
la acción a tomar una vez que el usuario haga clic en el botón “submit”. En este ejemplo se
enviará a una URL.
El tag Form utiliza dos maneras de enviar la información de su formulario:
get – Es la menos segura esto es porque la información capturada en el formulario
se envía por medio de la URL. Es decir, la URL tiene insertado datos que fueron
ingresados al formulario y es visible para el usuario final.
post – la información capturada en el formulario se envía de manera oculta
utilizando el “body” del HTTP Request. Por tema de seguridad siempre que
enviemos información de un formulario, deberemos utilizar el método “post”.
Para la propiedad action del “form” que platicamos anteriormente, vamos a crear una
nueva ruta de tipo post. Cada formulario debe de tener su propia ruta, es decir por cada
formulario debemos definir una clase “Route::post” en el archivo web.php como se
muestra a continuación:
Route::post('cursos',[CursoController::class, 'store'])->name('cursos.store');
En el código anterior le estamos diciendo que la clase controlador “CursoController” en su
método “store()” es el que se va a encargar de controlar lo que pasa con esa ruta (lo que
esa ruta va a realizar) y para acceder a la ruta lo hacemos a través del alias ‘cursos.store’
con el método “route()”. Este alias es el que vamos a agregar a la propiedad “action” del
formulario.
Para agregar el token, dentro del formulario se agrega una directiva de Blade “@csrf”
<form action="cursos.store" method="post">
@csrf
Esta directiva @csrf agrega un input oculto con la propiedad “ name = ‘token’ “ y es la
encargada de generar un token para este formulario.
La directiva “@csrf” además de crear el token también lleva un registro de los tokens que
se generan. En este registro por cada token generado crea una relación del URL que lo
manda, así como el URL que recibe (el valor de la propiedad “action” del formulario). Con
ello garantiza que, aunque de manera local adultere el formulario, este no sería
procesado.
Otro punto interesante de los Token es que estos tienen un tiempo de vida. Laravel
después de cierto tiempo va eliminando esos registros de los token, por ende, si tenías
una pagina abierta con un formulario, pero dejaste inactiva por mucho tiempo la página,
al querer procesar ese formulario te aparecerá como que la pagina ya expiro. Si
trabajáramos con PHP puro todos estos temas de seguridad tendríamos que hacerlos
nosotros mismos.
Para recibir lo que se manda desde un formulario, al método “store()” se le tiene que
pasar un parámetro de tipo Request. Este objeto de tipo Request es el encargado de
interactuar con la solicitud actual HTTP que maneja la aplicación, así como recuperar los
inputs (los datos de un formulario), las cookies y los archivos que se enviaron con la
solicitud.
public function store(Request $request)
{
}
Para ver lo que trajo el objeto “Request”, hacemos un “return” a la variable “$request”
invocando a su método all()
public function store(Request $request)
{
return $request->all();
}
Estas son hasta el momento las clases “Route” creadas en el archivo “web.php”
Route::get('/', HomeController::class);
Route::post('cursos',[CursoController::class, 'store'])
->name('cursos.store');
Una vez creada la nueva ruta (archivo web.php) y su respectivo método de la ruta. Ahora
en el archivo view (show.blade.php) podemos definir la propiedad href=”” con el valor que
se definió como alias de la nueva ruta (en este ejemplo ‘cursos.edit’). Esto lo hacemos
imprimiendo el método “route()” y pasándole 2 parámetros
1. El primer parámetro es el URL en este caso el alias definido para este URL
2. El segundo parámetro es el id que ya tiene la variable $curso.
<a href="{{route('cursos.edit',$curso->id)}}">Editar Curso</a>
Hasta este punto si ingresamos desde el formulario un nuevo registro para guardar en la
base de datos, al guardar la información nos redireccionará a la página “show.blade.php”
y nos despliega una página con la información que capturamos en el formulario.
Si damos clic en el enlace “editar curso” este nos mandara a una página en blanco, pero lo
que nos interesa es que en el URL vendrá el ID que necesitamos para obtener el registro
de la base de datos
http://localhost/salon/public/cursos/8/edit
Recuperar datos de la base de datos para llenar el formulario a editar
Realizado el punto anterior, ahora en el archivo controlador, dentro del método para esta
ruta (en este caso el método “edit()” ) Recuperamos el registro de ese id en específico a
través del método “find()” y lo guardamos en una variable.
Recuerde que con Return y la variable podemos realizar una prueba y verificar que
información es la que recupero el método “find()” de la base de datos antes de mandar a
guardar la información en la base de datos.
Abreviatura para recuperar datos de la base de datos para llenar el formulario a editar
Otra forma de recuperar los registros de la base de datos es pasando el parámetro del tipo
de la clase del modelo, es decir, si la clase modelo es ‘curso’ entonces pasamos el
parámetro de tipo curso.
Si pasamos como parámetro el tipo de la clase modelo, Laravel entiende que quiero que la
variable “$curso” sea una instancia de la clase curso Modelo cuyo id (del registro a
recuperar) sea lo que estemos mandando por el parámetro. De esta manera escribiríamos
menos código.
Llenar el formulario HTML con los valores recuperados de la base de datos para su edición
El siguiente paso es sustituir el “return $curso” por la ruta de la vista. Esta vista aun no la
hemos creado. Este archivo vista lo creamos dentro de la carpeta
view/cursos/edit.blade.php
Hasta este punto este es el código del archivo edit.blade.php tendría este aspecto: (aun
no nos faltaría poner en el formulario los datos recuperados en la base de datos.
@extends('layouts.plantilla')
@section('content')
<h1>En esta pagina podras editar un curso desde el view usando blade</h1>
<form action="{{route('cursos.store')}}" method="POST">
@csrf
<label>
Nombre:
<br>
<input type="text" name="nombre">
</label>
<br>
<label>
Descripcion :
<br>
<textarea name="descripcion" rows="5">
</textarea>
</label>
<br>
<label>Categoria
<br>
<input type="text" name="categoria">
</label>
<br>
<br>
<button type="submit">Actualizar registros</button>
</form>
@endsection
Para llenar los registros del formulario con los registros recuperados de la base de datos
(recuerde que en la variable “$curso” se almaceno los registros recuperados en la base de
datos. Por lo tanto, si el tag HTML soporta la propiedad “value”, entonces en este valor se
imprime la variable $curso->nombre como se muestra a continuación:
<input type="text" name="nombre" value="{{$curso->nombre}}">
El código completo seria (aun nos falta crear una ruta que será la que reciba el formulario
al dar clic al botón “actualizar registros”)
@extends('layouts.plantilla')
@section('content')
<h1>En esta pagina podras editar un curso desde el view usando
blade</h1>
<form action="{{route('cursos.store')}}" method="POST">
@csrf
<label>
Nombre:
<br>
<input type="text" name="nombre" value="{{$curso->nombre}}">
</label>
<br>
<label>
Descripcion :
<br>
<textarea name="descripcion" rows="5">{{$curso-
>descripcion}}</textarea>
</label>
<br>
<label>Categoria
<br>
<input type="text" name="categoria" value="{{$curso-
>categoria}}">
</label>
<br>
<br>
<button type="submit">Actualizar registros</button>
</form>
@endsection
Creación de una nueva ruta (archivo web.php) y método (archivo controlador) para el
nuevo formulario
Recuerde que por cada formulario se tiene que crear su propia ruta por lo que a
continuación necesitamos crear una nueva ruta en el archivo “web.php”. Esta nueva ruta
será la encargada de actualizar el registro en la base de datos a través de su método del
controlador.
Como se va a traer información del formulario usamos POST. Con esto ocultamos la
información del formulario (recuerde que “GET” envía a través del URL los datos del
formulario y por ende es visible al usuario final)
Configuración del método “put” para actualizar la información en la base de datos
IMPORTATE Laravel recomienda que cuando queramos actualizar un registro en vez de
usar el método POST utilices el método “PUT”.
Route::put('cursos/{curso}', [CursoController::class, 'update'])-
>name('cursos.update');
Sin embargo, los formularios HTML solo soportan 2 métodos: “GET” y “POST”. Para lograr
definir el formulario como método “put” necesitamos realizar 2 acciones
1. Definir la propiedad “method” del formulario como “POST” (method=”POST”)
2. Pasarle en el cuerpo del formulario la directiva @method('put’)
El siguiente paso es dentro del método, actualizar la variable $curso con lo que tiene la
variable $request. Esto lo hacemos por cada columna que tiene la tabla de la base de
datos
$curso->nombre = $request->nombre;
$curso->descripcion = $request->descripcion;
$curso->categoria = $request->categoria;
Antes de guardar revisamos que datos se han guardado en la variable “$curso” con un
return
return $curso;
}
Si todo esta correcto sustituimos el return por el método “save()” para ahora si actualizar
el registro en la base de datos.
public function update(curso $curso, Request $request)
{
$curso->nombre = $request->nombre;
$curso->descripcion = $request->descripcion;
$curso->categoria = $request->categoria;
$curso->save();
}
IMPORTATE: Recuerde que “Tinker” si queremos guardar un nuevo registro tiene que ser
una instancia que no haya guardado algún registro en la base de datos, de lo contrario si
usamos una instancia que ya ha guardado información en la base de datos va a detectar
que tiene la misma ID (aunque hayamos modificado los otros campos) y por ende lo que
hará será editar la información del registro de esa ID en vez de guardarlo como un registro
nuevo. Ese mismo principio es el que aplica aquí. Si observa el método “store()” solo trae
como parámetro la información del formulario (“Request $request), pero el método
“update()” trae dos parámetros: la información del formulario (“Request $request”), pero
también trae el registro de la base de datos (“curso $curso”) por ende esta variable ya
tiene un id asignado y al editar los demás campos lo que realiza en la base de datos sería
una actualización y no un registro nuevo.
Como último punto, una vez actualizado el registro en la base de datos redireccionamos a
la página donde me mostrará los detalles del curso (página show.blade.php, su alias es
cursos.show)
El código para esta validación se hará en el archivo controller. Dentro del método que
asigna los valores y lo guarda en la base de datos. Este será el primer código por
ejecutarse dentro del método (antes de asignar los valores y por supuesto antes de
guardar con el método “save()” los valores en la base de datos) ya que si la validación es
incorrecta interrumpe el flujo del código.
Es importante señalar que este código únicamente validaría la información como falso o
verdadero para continuar (validación verdadera) o detener (validación falsa) el flujo del
código. En este último punto (validación falsa) se podría comparar con deshabilitar el
botón “submit” del formulario (por lo que la pagina se refrescaría y se perdería la captura,
evidentemente se detiene el flujo y no se guardaría la información en la base de datos).
Por lo que todavía tendríamos que indicarle que hacer si la validación fue falsa, como por
ejemplo que campos fueron incorrectos
Con esto le estoy diciendo que el componente HTML con el atributo name=’nombre’ tiene
2 reglas
1. Que es un campo requerido
2. Que solo puede capturar un máximo de 10 caracteres.
En la siguiente página
https://laravel.com/docs/9.x/validation#available-validation-rules podemos encontrar
todas las validaciones y sus funciones.
Es importante señalar que Laravel recomienda tener las validaciones en otro archivo y no
dentro del archivo controller, pero cuando son validaciones muy pequeñas se puede
poner dentro de los métodos del archivo controller como en el ejemplo anterior. Más
adelante (en el capítulo “que son los “Form Request”) vamos a explicar cómo tener las
validaciones en otro archivo y ligarlos al archivo controlador.
Especificar los componentes con error (mostrar mensajes de error)
Esto se hace en el archivo vista donde tenemos el formulario y para ello vamos a utilizar la
directiva de Blade “@error” y la variable PHP “$message”.
La variable “$message” es donde en caso de haber algún error se guardar de manera
interna el registro de ese error.
Este código se agregaría por cada input o componente como e muestra a continuación:
<label>
Nombre:
<br>
<input type="text" name="nombre" value='{{$material->nombre}}'>
</label>
<br>
Una vez reemplazado el contenido de los archivos al español, el siguiente paso es indicarle
a Laravel que queremos usar la carpeta “es” y no la carpeta “en”.
Para esto debemos ir a la carpeta “config” que se encuentra en la raíz del proyecto y
abrimos el archivo “app.php”. Este archivo tiene la configuración general de nuestro
proyecto.
Evitar perder los datos del formulario cuando la validación sea falsa
Esto se hace en la vista que tiene el formulario.
Al llenar un formulario y enviarlo pero la validación es negativa, lo que hace el sitio web es
refrescar la pagina y por ende perdemos lo que se había capturado. Para evitar perder la
captura cuando la validación es errónea, usamos el método “old()”.
La sintaxis del método “old(parametros1, parametro2)” es:
El parametro1 es el valor del atributo name del componente html
El parámetro2 es opcional y es para especificar el valor por default con el que
iniciara.
Este segundo parámetro es idea para los formularios que son para actualizar los datos. Ya
que por default le ponemos el valor del registro y con el método old no perdemos las
ediciones realizadas en los componentes. Así si editamos ese componente no se perdería
la información en caso de que la validación sea falsa.
En la atributo “value” le asignamos como valor el método “old()” pasando a este método
como parámetro el valor que tenga el atributo “name” del input.
<input type="text" name="nombre" value='{{old('nombre')}}'>
El código completo del formulario sería
<form action="{{route('materiales.storeM')}}" method="POST">
@csrf
<label>
Nombre:
<br>
<input type="text" name="nombre" value='{{old('nombre')}}'>
</label>
@error('nombre')
<small>*{{$message}}</small>
@enderror
<br>
<label>
Descripcion :
<br>
<textarea name="descripcion"
rows="5">{{old('descripcion')}}</textarea>
</label>
@error('descripcion')
<small>*{{$message}}</small>
@enderror
<br>
<label>Cantidad
<br>
<input type="number" name="cantidad" value='{{old('cantidad')}}'>
</label>
@error('cantidad')
<small>*{{$message}}</small>
@enderror
<br>
<br>
<button type="submit">Ingresar registros</button>
</form>
Como se explico anteriormente para usar el método old en un formulario que se utiliza
para editar la información de la base de datos debería de usarse
Creación
Para crear un archivo “Form Request” se hace desde la línea de comandos con la
instrucción:
/**
* Get the validation rules that apply to the request.
*
* @return array
*/
public function rules()
{
return [
//
];
}
}
Como podrá observar el archivo creado tiene una clase llamada “StoreCurso” de tipo
“FormRequest” y dentro de esta clase se definen 2 métodos:
authorize() – Dentro de este método se establece la lógica necesaria para verificar
si el usuario que está intentando ingresar datos a la base de datos cuenta con los
permisos para poder hacerlo; por ejemplo, que tenga los permisos de
administrador, creador de contenidos, editor de contenido o algún permiso que le
permita escribir en la base de datos.
Si los permisos son correctos entonces regresa el valor de “true” en caso de que el
usuario no cuenta con los permisos regresa el valor de “false”. Regresar el valor “
false” es el valor predeterminado.
Solo si regresa el valor de “true” continua al método siguiente (rules()), en caso
contrario la autorización falla y regresa un mensaje diciendo usuario no autorizado.
rules() – En este método entre corchetes se van a agregar todas las validaciones
que necesitemos para este formulario como se muestra a continuación:
public function rules()
{
return [
//
'nombre'=>'required',
'descripcion'=>'required',
'categoria'=>'required'
];
}
En otras palabras, dentro del método Attribute por ejemplo, definimos el atributo
“nombre” (el valor de name=”nombre”) y en caso de encontrarlo sustituirá el atributo
“nombre” por el mensaje/palabra que definimos.
public function attributes()
{
return [
'nombre' => 'nombre del curso',
];
}
Con este método sustituimos del mensaje predeterminado de error: “El campo nombre es
obligatorio”, a el mensaje: “El campo nombre del curso es obligatorio”.
Con este método va a recorres cada uno de los componentes del formulario buscando
en su propiedad name el valor de “descripcion” y una vez que encuentre el
componente validara el tipo de error, si el error es que el componente esta vació
(required) entonces sustituirá el mensaje de error predeterminado y mostrara el
mensaje personalizado: “Nuevo mensaje de error – campo obligatorio”
El problema con este procedimiento es que tenemos que declarar registro por registro del
formulario y asignarle su valor correspondiente. Esto puede ser más complejo ya que es
común tener 2 métodos que utilizan estos registros, el método utilizado para guardar
(store) la información en la base de datos y el método utilizado para editar (update) la
información de la base de datos.
Con la asignación masiva podremos simplificar lo anterior en una sola línea de código,
independientemente de cuantos registros sean.
$curso = curso::create($request->all());
Si recuerdan el método “all()” regresa un arreglo donde muestra todo lo que se estaba
enviando desde el formulario como se muestra en el siguiente ejemplo:
{"_token":"TadynjTEepN3erqHtHbsiBOL5mDS570UuCiTGhtb","nombre":"JavaScript
","descripcion":"Complemento para Css y HTML","categoria":"Programacion"}
Como podrá observar lo que regresa “all()” son las propiedades (en este ejemplo
“nombre”) con sus respectivos valores (en este ejemplo “JavaScript”), por lo que de
manera interna dentro del método “create()”, este código será el que sustituirá al código
siguiente:
'nombre' => $request->nombre,
'descripcion' => $request->descripcion,
'categoria' = $request->categoria
$curso->update($request->all());
4. Redireccionar al catalogo
public function destroy(curso $curso)
{
$curso->delete();
return redirect()->route('cursos.index'); //redireccion a
cursos.index
}
Dentro de este método vamos a ejecutar otro método llamado “delete() del tipo modelo.
$curso->delete();
Normalmente en el archivo “web.php” tendremos más de 5 rutas por cada CRUD (create,
read, update y delete) realizado en nuestro proyecto. Con Route::resourse podemos
agrupar todas estas rutas en una sola línea de código (siempre y cuando se hayan seguido
las convenciones en los nombres asignados)
Route::post('cursos',[CursoController::class, 'store'])-
>name('cursos.store');
Para esto nos sirve enlistas las rutas en línea de comandos ya que al abreviar (agrupar)
todas las rutas en una sola línea de comando podemos ver cual es su alias, el método que
se utiliza en el archivo controlador y su ruta “identificativa”.
La segunda tabla es listando las rutas pero usando una sola línea de código
Route::resource('cursos',CursoController::class);
Es importante señalar que el método Route resource solo le pasamos como parámetro la
URL significativa y como segundo parámetro la clase del controlador.
De manera interna Laravel ha creado las 7 rutas significativas que se encargaran de
administrar el CRUD (créate, read, update y delete).
Además, este método (Route resource ) ha determinado que las rutas que
necesitan un variable, el nombre de la variable sería el singular del URL
identificativa. 'cursos/{curso}'
También ha identificado que el alias empezarían con el nombre de la ruta
identificativa.nombreAccion, por ejemplo para guardar un registro en la base de
datos el alias seria 'cursos.store', cursos.edit – para la acción de editar un
registro, cursos.show para la acción de mostrar un registro, etc.
Lo mismo para los nombres de los métodos donde se realizan las acciones del
CRUD en el archivo controlador.
Es por esto por lo que es super importante seguir las convenciones que nos da Laravel (al
momento de ir creando las rutas, alias para las rutas y métodos en el controlador) y con
ello podemos abreviar las rutas y escribir mucho menos líneas de código.
2. Dentro del método “boot()” definimos otro método Route::resourceVerbs() con las
palabras y sus respectivas sustituciones, quedando el código completo del método
“boot()” de la siguiente manera:
public function boot()
{
//
// Paginator::useBootstrap();
Route::resourceVerbs([
'create' => 'crear',
'edit' => 'editar',
]);
}
Si volvemos a correr en línea de comando la instrucción “php artisan r:l” nos mostrará la
lista de rutas con los cambios realizados.
Hacer esto implicaría que también se cambien el alias y por ende fallaría toda la aplicación
(enlistamos todas las rutas para que se aprecie lo anterior)
Para lograr que el método “Route::resource()” solo cambie el URL sin mover el alias le
agregamos el método “names(‘URLsustituto’)”.
Route::resource(‘materiales’,CursoController::class)->names(‘cursos’);
Con este método le estamos indicando que para las rutas utilice la palabra “materiales” y
que para el alias utilice la palabra “cursos”. Es decir con el método ‘names(‘nombreAlias)”
le indicamos cual será el nombre del alias.
Para tener una mejor perspectiva listamos nuevamente la lista de rutas en línea de
comando
Otro posible error que nos sale es que también se cambia el nombre de las variables.
Antes teníamos $curso y ahora tendríamos $materia
Esto cambiaria el nombre de las variables por el de curso como se muestra a continuación
en el listado de rutas en línea de comandos.
23 – Como generar URLs amigables.
Como podrá observar en nuestro proyecto las URLs que hemos generado no son muy
descriptivas, Por ejemplo, cuando pasamos la IP por el URL para obtener un registro,
generamos una dirección similar a la siguiente
http://localhost/salon/public/materiales/55
Lo importante de un sitio que no describe mucho su contenido puede ser perjudicial para
los buscadores y por consecuencia ser más difícil aparecer en la búsqueda de resultados
de los buscadores de manera organiza (las búsquedas orgánicas con aquellas que no son
de paga). Los motores de búsqueda “recompensan” aquellos sitios web que son claros y
descriptivos para el usuario final. Por se recomienda que en vezde tener una URL
http://localhost/salon/public/materiales/55 tengamos una URL asi
http://localhost/salon/public/materiales/Laptop-Gamer-Acer
Para poder utilizar el método slug necesitamos definir que vamos a utilizarlo con un
use Illuminate\Support\Str;
Si observamos el código podremos ver que fuera del “return” hemos guardado en una
variable (“$nombre”) el enunciado (cada enunciado será de 3 palabras). Esto se hizo de
esta manera para que lo que tenga la viable $nombre se le asigne tanto al campo
‘nombre’ como al campo ‘slug’. De otra manera tendríamos un enunciado para el campo
nombre y otro enunciado para el campo ‘slug’ y lo que nosotros queremos es que tanto el
nombre como el slug tengan los mismo.
Corremos el factory para generar los datos de prueba en la base de datos. Recuerde que
para correr el factory necesitamos 2 puntos
1. En el archivo base Seed (DatabaseSeeder.php) agregar el código
curso::factory(25)->create();
Este código nos dice que la propiedad “href” nos vamos a dirigirnos al alias “cursos.show”
y vamos a pasar un valor $item. El valor del $item es el id en la base de datos.
Dando como resultado un URL de la siguiente manera:
http://localhost/salon/public/cursos/9
Es importante señalar que si a la variable $item->id le quitamos el “->id” dejando solo
$item, pasara igualmente solo el numero del id. Esto es posible ya que Laravel pasa el
primer registro de la tabla siempre y cuando cumpla los siguientes requisitos: sea un
campo id, autonumérico y sea “Primarykey”. En otras palabras, pasara el valor del id si el
primer campo de la tabla cumple con los estándares para ser un campo ID, de lo contrario
se tiene que especificar el campo (por ejemplo, “$item->nombre”).
Como mencionamos anteriormente la propiedad “href” nos va a dirigir al alias
“cursos.show”, para saber que acción realiza esta ruta, en el archivo controlador,
buscamos el método show (buscamos el alias en el archivo web.php y nos dirigimos a su
método del alias) y veremos el siguiente código
public function show(curso $curso)
{
return view('cursos.show', compact('curso'));
}
podremos observar que este método recibe un parámetro que es donde va a recibir el ID
que envío el archivo view. Si analizan el código podrán observar que el parámetro tiene
una
variable (“$curso”) de tipo “curso”, es decir del tipo de la clase del modelo.
Definir el tipo de la clase del modelo nos permite abreviar código. Con esto Laravel
entiende que quiero que la variable “$curso” sea una instancia de la clase curso Modelo
cuyo id (del registro a recuperar) sea lo que estemos mandando por el parámetro. De esta
manera escribiríamos menos código.
Es decir, este código
public function store($curso)
{
$curso= curso::find($curso);
return $curso;
}
Regresa lo mismo que este código
public function store(curso $curso)
{
return $curso;
}
Es importante señalar que es una mala práctica sobrescribir el método “original” que
viene por defecto en el framework, por lo que para poder sobre escribirlo se hace desde el
archivo modelo como se muestra a continuación
class curso extends Model
{
use HasFactory;
public function getRouteKeyName()
{
return 'slug';
}
}
Resumiendo, para crear URL´s que sean más descriptivas debemos tener un campo en la
tabla con nombre slug y posteriormente sobre escribir el método getRouteKeyName() en
el archivo modelo. Con esto el método del controlador en vez de buscar el id y buscar el
registro de ese Id, buscara el slug y el registro perteneciente a ese slug. Por lo que la URL
mostrará el contenido del slug y no el id. Esto con la finalidad que los motores de
búsqueda nos puedan posicionar de manera orgánica.
<body>
<header>
<h1>Curso de Laravel</h1>
<nav>
<ul>
<li><a href="">Home</a></li>
<li><a href="">Cursos</a></li>
<li><a href="">Nosotros</a></li>
</ul>
</nav>
</header>
@yield('content')
</body>
Ahora en el archivo vista plantilla general en la lista de navegación que acabamos de crear
vamos a poner sus respectivos enlaces.
o route(‘home’) para Home
o route(‘cursos.index’) para Cursos
o route(‘nosotros’) para nosotros. Este ultimo no hemos creado ni su ruta ni
su archivo vista, por lo que si corremos la aplicación nos generara un
error. El siguiente paso es crear su ruta y su archivo vista.
<body>
<header>
<h1>Curso de Laravel</h1>
<nav>
<ul>
<li><a href="{{route('home')}}">Home</a></li>
<li><a href="{{route('cursos.index')}}">Cursos</a></li>
<li><a href="{{route('nosotros')}}">Nosotros</a></li>
</ul>
</nav>
</header>
@yield('content')
</body>
Ahora nos dirigimos al archivo “web.php” para crear la ruta ‘nosotros’. Con el método
view
Route::view('URL','ArchivoView')->name('alias');
Este método “view()” solo lo vamos a utilizar cuando queremos mostrar contenido
estático, es decir que no nos vamos a conectar con nuestra base de datos. Simplemente
queremos mostrar una vista.
Este archivo lo vamos a configurar de la siguiente manera
Route::view('nosotros','nosotros')->name('nosoteos');
Esto quiere decir
o El valor del la URL es ‘nosotros’ (parámetro 1)
o El nombre del archivo vista será ‘nosotros’ (parámetros 2 – el nombre
completo del archivo vista es “nosotros.blade.php”)
o Y su alias será ‘nosotros’ (método “name()”)
Creación de la vista
Para esto vamos a la carpeta view y desde esa carpeta creamos el archivo
“nosotros.blade.php”. dentro de este archivo pondremos el siguiente código
@extends('layouts.plantilla')
@section('title', 'Pagina Nosotros')
@section('content')
<h1>Bienvenido a la página Nosotros (index) desde el view con plantilla
usando blade</h1>
@endsection
Este código solo es provisional ya que mas adelante vamos a modificarlo.
Como podrán ver en la imagen imprime el valor de “true” ya que en este momento la
página se encuentra en el URL home (está en la raíz del o página principal).
Ahora en vez de incrustar código PHP dentro del código HTML podemos usar la directiva
de Blade @dump() y el resultado sería exactamente lo mismo
<li><a href="{{route('home')}}">Home</a>
@dump(request()->routeIs('home'))
</li>
Entonces con esta directiva de Blade @dump(request()->routeIs('home')) podemos
identificar en que ruta nos encontramos.
Identificar la ruta nos sirve para saber si nos regresa un valor falso o verdadero, por
consiguiente, si nos regresa un valor verdadero buscamos que se aplique una clase
especifica (la clase ‘active’), de lo contrario que la clase este vacía.
Esto lo haríamos dentro del siguiente código HTML
<li><a href="{{route('home')}}" class="{{aqui se aplica el if}}">Home</a>
En vez de usar un if para saber si regresa un valor verdadero o false usaremos una
condicional utilizando operadores ternarios
Primero llamamos a la función request()->routeIs('home')
Después de la función ponemos el signo de interrogación (al poner un signo de
interrogación es como si todo el código lo hubiéramos puesto dentro de un if)
request()->routeIs('home') ?
Luego del signo de interrogación va lo que quiero que imprima en caso que regrese
verdadero request()->routeIs('home') ? ‘active’
Al final poner 2 puntos para indicar que imprimiría en caso de que sea falso (como
el else). Para este ejemplo lo dejamos vacio por que no queremos que se imprima
nada request()->routeIs('home') ? ‘active’ : ’’
Por lo tanto, el código completo para la clase seria
<a href="{{route('home')}}" class="{{request()->routeIs('home') ? 'active' :
''}}">Home</a>
IMPORTANTE: No basta con agregar la clase=’active’, debemos crearla y definirla. Para ello
dentro del tag <head> agregamos el tag <style></style> y entonces definimos la clase
“active” como sigue:
<style>
.active{
color:green;
font-weight: bold;
}
</style>
El problema que surge es que si damos clic en cualquiera enlace del catalogo (por ejemplo
“QUIA MAJORES MODI BEATAE”) o nos vamos a crear un nuevo curso, aunque nos
encontremos en la sección de cursos el enlace se desactiva ya que actualmente solo esta
codificado para una sola ruta (“cursos.index”)
Para resolver esto sustituimos la ruta “cursos.index” por “cursos.*”.
<li><a href="{{route('cursos.index')}}" class="{{request()-
>routeIs('cursos.*') ? 'active' : ''}}">Cursos</a></li>
Al poner asterisco en la ruta es un comodín. Con este comodín le indicamos que sustituya
el asterisco por lo cualquier etiqueta, basta que la ruta empiece con “cursos.” entonces lo
tome como verdadero.
Con esto podremos estar en la ruta “cursos.edit” o “cursos.create” o “cursos.show” y
siempre mostrarse activo ya que solo toma en cuenta “cursos.”
Para llamar a la plantilla header dentro de la plantilla base lo hacemos a través de una
directiva de Blade llamada “@include(‘rutaArchivoVistaHeader’)”
@include('layouts.partials.header')
Recuerden que la búsqueda de los archivos view los hace desde la carpeta view del
proyecto la cual toma como si fuera la raíz de la ruta.
Para crear la plantilla footer hacemos exactamente lo mismo
1. Creamos el archivo footer.blade.php dentro de la carpeta “partials”
2. Al archivo footer.blade.php le ponemos un código de prueba solo que aquí hay que
usar los Tags <footer></footer>
<footer>
<small>Esto es el pie de pagina</small>
</footer>
@yield('content')
@include('layouts.partials.footer')
</body>
</html>
Como podrá observar de esta manera mantenemos mas “limpia” la plantilla base.
Como podemos observar la variable MAIL_MAILER tiene valor SMTP lo que quiere decir
que utilizara el protocolo SMTP para envío de emails.
Para efectos de este proyecto vamos a utilizar mailtrap como proveedor. Mailtrap es un
servidor “falso” que utiliza el protocolo SMTP para que los desarrolladores realicen
pruebas, vean el diseño del email y compartan emails desde su proyecto en desarrollo sin
realizar spam. En otras palabras, mailtrap no envía los emails a sus destinatarios. Mailtrap
intercepta ese email y te lo muestra en su la propia bandeja de entrada de mailtrap tal
cual le llegaría al destinatario. Por su puesto que cuando el proyecto pase a producción
habría que configurar estos datos con otro proveedor de correos electrónicos.
Para poder conectarnos con mailtrap debemos de tener una cuenta, de lo contrario
tendríamos que registrarnos
Una vez que ingresamos podemos ver la siguiente ventana de bienvenida
Ahora en el archivo “.env” debemos buscar estas variables y sustituir sus valores por los
que el archivo Mailtrap nos proporciona.
Nota: en el caso de las variables MAIL_USERNAME y MAIL_USERPASSWORD asegúrate de
no llevarte espacios en blanco antes y después de los caracteres.
La variable MAIL_ENCRYPTION es opcional
Esto me va a generar una nueva carpeta llamada “Mail” dentro de la carpeta “app” y
dentro de la carpeta “Mail” me habrá creado un archivo “ContactanosMailable.php”.
El código completo del archivo “ContactanoMailable.php” es el siguiente:
<?php
namespace App\Mail;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Mail\Mailable;
use Illuminate\Queue\SerializesModels;
/**
* Create a new message instance.
*
* @return void
*/
public function __construct()
{
//
}
/**
* Build the message.
*
* @return $this
*/
public function build()
{
return $this->view('view.name');
}
}
En este archivo es donde puedo personalizar lo que va a ir dentro del correo electrónico.
Por ejemplo, para definir el asunto de un correo electrónico se crea una propiedad pública
llamada “subject” dentro de la clase “ContactanosMailable”
... //código
...//código
}
Es importante señalar que es sumamente importante escribir correctamente $subject ya
que si por error nos faltara una letra el asunto que escribimos no se enviaría y en su lugar
se enviaría como asunto “contáctanos Mailable” (que es el nombre de nuestro archivo
Mailable).
Nota: todas las propiedades que aquí definamos estas son como variables globales que
pueden pasarse al archivo vista.
Ahora para definir el cuerpo del email, este se realiza dentro del método build(). Por
default la definición de este método regresa un archivo vista.
public function build()
{
return $this->view('view.name');
}
Con esto queremos resaltar el cuerpo del correo electrónico se construirá dentro de un
archivo vista con formato HTML.
Para ello, dentro de la carpeta view vamos a crear otra carpeta llamada “emails” y dentro
de esta carpeta crearemos el archivo vista “contactanos.blade.php” con lo cual la ruta
quedaría “emails.contactanos” como se muestra a continuación:
Como podrán ver dentro del body tenemos las etiquetas <h1> y <p> las cuales tienen
como titulo “Correo Electrónio” y de párrafo “Este es el primer correo electrónico que
mandaré por Laravel”.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<style>
h1{
color:blue;
}
</style>
</head>
<body>
<h1>Correo Electrónico</h1>
<p>Este es el primer correo electrónico que mandaré por Laravel</p>
</body>
</html>
Y de esta manera es que podrías personalizar tus emails tanto como desees
Dentro de ese archivo le agregamos una etiqueta <li> y dentro de la etiqueta <li> otra
etiqueta anchor <a href=””> la cual llevara por nombre “Contáctanos”.
<li><a href=""></a>Contáctanos</li>
Si recuerdan en el archivo “web.php” creamos una ruta que será el disparador (trigger)
que enviara el email, esta ruta es “contáctanos”. Lo que vamos a hacer es ponerle un alias
y con ello el código quedará de la siguiente manera:
Route::get('contáctanos', function () {
$correo = new ContactanosMailable;
Mail::to('jacgms@hotmail.com')->send($correo);
return "Mensaje enviado";
})->name('contactanos.index');
namespace App\Http\Controllers;
use Illuminate\Http\Request;
}
public function store()
{
}
}
En el archivo controlador en el método “index()” le vamos a pedir que nos retorne una
vista. Este archivo vista va a estar dentro de una carpeta llamada contactanos y se va a
llamar index
public function index()
{
return view('contatanos.index');
}
@section('title', 'Contactanos')
@section('content')
<h1>Dejanos un mensaje</h1>
@endsection
En esta vista lo que deseamos es mostrar un formulario, donde el usuario pueda poner su
nombre, su correo electrónico y un mensaje que desee enviar.
Por lo que debajo de la etiqueta <h1> y antes de “@endsection” escribimos el siguiente
código
<form action="{{route('contactanos.store')}}" method="POST">
@csrf
<label>
Nombre:
<br>
<input type="text" name="name">
</label>
<br>
<label>
Correo Electrónico:
<br>
<input type="text" name="email">
</label>
<br>
<label>
Mensaje:
<br>
<textarea name="mensaje" rows="5"></textarea>
</label>
<br>
<button type="submit">Enviar mensaje</button>
</form>
Guardamos y revisamos (nos debe desplegar una página web similar a la siguiente)
Hasta este punto si le damos clic al botón “enviar” del formulario nos enviara el correo
electrónico que podemos revisar en la bandeja de Mailtrap (en el capítulo anterior se
explicó como configurar en Laravel el correo electrónico y que es Mailtrap y su
funcionamiento).
Entonces si entramos al archivo vista podremos acceder e imprimir el contenido que tenga
la propiedad que definimos en el archivo “Mailable”. En este ejemplo el contenido de la
propiedad se imprimirá como párrafo después de “Este es el primer correo electrónico
que mandare por Laravel” en el cuerpo del email.
<body>
<h1>Correo Electrónico</h1>
<p>Este es el primer correo electrónico que mandaré por Laravel</p>
<p>
{{$contacto}}
</p>
</body>
Teniendo claro lo anterior, la forma que tenemos para pasar la información a nuestro
correo electrónico es la siguiente.
Recuperar la información del formulario en una variable
Vamos al archivo controlador “ContactanoController” en el método “store()” le agrego
como parámetro la variable $request como tipo Request.
public function store(Request $request)
{
.....
}
Dentro de este mismo método donde se está creando la instancia de la clase Mailable, le
voy a pasar información al constructor a través de la variable $request y ejecutando a su
método “all()”.
$correo = new ContactanosMailable($request->all());
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Mail\ContactanosMailable;
use Illuminate\Support\Facades\Mail;
Si recuerdan en este mismo archivo Mailable, se había creado una propiedad de tipo
publico llamado $contacto.
Entonces a esta propiedad le vamos a asignar el valor que trae el parámetro que recibe el
método “_construct()”. Observe que la propiedad se definede tipo publica y con signo de
pesos. Pero al definirla dentro del método “_construct()”, se utiliza $this y no lleva signo
de pesos el nombre de la propiedad.
$this->contacto = $contact
Aun no podemos hacer una prueba enviando el mail ya que en el archivo view tenemos el
siguiente código
{{$Contacto}}
En blade este es un similar a un echo de PHP, es decir imprimir, por lo que espera un
string y nosotros estamos enviando un arreglo.
Por lo que nos arrojaría el siguiente error.
htmlspecialchars() expects parameter 1 to be string,
array given
Entonces si existe la variable “info” quiero que imprimas una alerta, y lo que se va a
imprimir es lo que trae la variable de sesión “info”
@if (session('info'))
<script>
alert("{{session('info')}}")
</script>
@endif
@section('title', 'Contactanos')
@section('content')
<h1>Dejanos un mensaje</h1>
<form action="{{route('contactanos.store')}}" method="POST">
@csrf
<label>
Nombre:
<br>
<input type="text" name="name">
</label>
@error('name')
<p><strong>{{$message}}</strong></p>
@enderror
<br>
<label>
Correo Electrónico:
<br>
<input type="text" name="correo">
</label>
@error('correo')
<p><strong>{{$message}}</strong></p>
@enderror
<br>
<label>
Mensaje:
<br>
<textarea name="mensaje" rows="5"></textarea>
</label>
@error('mensaje')
<p><strong>{{$message}}</strong></p>
@enderror
<br>
<button type="submit">Enviar mensaje</button>
</form>
@if (session('info'))
<script>
alert("{{session('info')}}")
</script>
@endif
@endsection
La diferencia entre Breeze y Jestream es que por decirlo de alguna manera “Breeze”
cumple con las necesidades básicas para un registro y autentificación de un usuario,
mientras que Jestream proporciona muchas más funciones que van más allá del registro y
autentificación del usuario.
En ambos casos será necesario realizar la instalación de estos kits a nuestro proyecto de
Laravel.
Estos kits arman automáticamente tu proyecto con las rutas, controladores y vistas que se
necesita para registrar y autentificar a los usuarios en tu sistema.
Abrimos una ventana de línea de comandos (fuera de visual code) como por ejemplo “Git
Bash” y nos dirigimos a la carpeta de xampp/htdocs
Para dirigirnos directamente a esa carpeta podemos escribir la siguiente instrucción
cd /c/xampp/htdocs
Creamos el nuevo proyecto Laravel llamado breeze (en minúsculas todo el nombre del
proyecto) como se muestra a continuación:
Creado el nuevo proyecto de Laravel lo abrimos en el visual Code
Instalando Breeze
Primero, debe crear una nueva aplicación Laravel , configurar su base de datos y
ejecutar las migraciones de su base de datos. Una vez que haya creado una nueva
aplicación Laravel, puede instalar Laravel Breeze usando Composer:
Primero vamos a instalar los paquetes de Breeze usando Composer. Para esto en la línea
de comandos de visual code escribimos la siguiente instrucción
composer require laravel/breeze --dev
El siguiente paso es ejecutar el comando migrate en línea de comando para crear las
tablas necesarias para la autentificación (recuerde que previo a ejecutarse la instrucción
debimos haber ya creado la base de datos y configurado el archivo .env)
php artisan migrate
Una vez creadas las tablas en la base de datos el siguiente paso es ejecutar la instrucción
npm install
npm son las siglas de “node package manager”, básicamente es el mejorador de paquetes
de javascript, es decir nos permite instalar paquetes que se ejecutan del lado del cliente
(frondend).
NOTA: es importante que antes de ejecutar npm install se haya instalado “node.js”
https://nodejs.org/en/
Ahora tengo que crear un servidor de php (esta es una opción, podemos usar localhost) y
así poder trabajar con una URL. En línea de comando de visual code ejecutamos la
siguiente instrucción
php artisan serve
Hasta este punto Breeze ya es funcional, el registro de usuario y autentificación.
En conclusión, para usar el paquete Breeze debemos prácticamente correr las siguientes
instrucciones en ese orden y ya podríamos utilizar la autentificación y registro de usuarios
en nuestro proyecto.
Que es Jetstream
Breeze proporciona un simple y mínimo punto de partida para registros y autentificación
de usuarios, Jetstream aumenta esa funcionalidad con características más robustas y
stacks adicionales de tecnología frontend. Para aquellos que son nuevos en Laravel, se
recomienda aprender bien Breeze antes de Jetstream.
Jetstream proporciona un kit de módulos que incluye inicio de sesión, registro de usuarios,
verificación de correo electrónico, autentificación de dos factores, administración de la
sesión, soporte de APIs a través de Laravel Sanctum y administración de equipos (teams)
de trabajo (opcional). Jetstream está diseñado con Tailwind y si o si en su instalación
tenemos que escoger trabajar ya sea con Livewire o inertia.
Instalación de Jetstream
Lo primero que hay que saber es que JetStream tiene conflicto con Laravel 8. Esto
principalmente se debe a que JetStream trabajo con la directiva vite pero la directiva vire
trabaja a partir de Laravel 9. Laravel 8 en vez de trabajar con la directiva vite trabaja con la
directiva mix. Se estuvo investigando en internet y algunas personas comentan que
“Jetstream not working with Laravel 8”. Sin embargo es ALTAMENTE recomendado que
revise la documentación de Laravel en el apartado “Starter Kits”.
Por lo tanto, se recomienda que si usara JetStream sea con laravel 9. Dicho lo anterior, la
siguiente explicación está enfocada en Laravel 9
Después de instalar Jetstream debemos instalar y crear sus dependencias NPM y ejecutar
la migración, es decir debe de ejecutar los siguientes códigos en ese orden.
npm install
npm run build
php artisan migrate
una vez instalado jetstream la primera diferencia que podremos observar será que una
vez registrado e ingresado el usuario, este tendrá una opción (que no tiene Breeze) para
poder ver el perfil del usuario llamada “profile”.
Importante: En modo local para efectos de prueba es importante que escriba este
comando en línea de código (visual code)
php artisan serve
Esto habilitara un servidor virtual de php (como si la página estuviera en el hosting) y
poder probar las funciones por ejemplo cambiar el nombre, email, cambiar el avatar del
usuario, etc.
Si intenta probar la página con localhost ningún cambio se registrará en la base de datos
(no se conecta con ella para los update) si puede registrar nuevos usuarios solamente.
Por ende, se recomienda que preferentemente cree un servidor “php artisan serve”.
podremos ver por ejemplo que si queremos habilitar se muestre el “avatar” del usuario
registrado. Solo des comentamos “Feature::profilePhotos(),”
'features' => [
// Features::termsAndPrivacyPolicy(),
Features::profilePhotos(),
// Features::api(),
// Features::teams(['invitations' => true]),
Features::accountDeletion(),
],
Esto nos mostrara esta imagen donde en vez del nombre se muestra el avatar del usuario
Como nota importante es que si habilitamos que se vea el avatar del usuario y este no se
ve (como se muestra en la imagen)…
Esto habitara en la página de registro el checkbox para aceptar los términos y condiciones
Solo aceptando las políticas podrá registrarse el usuario.
Para modificar el contenido de las políticas y condiciones, esto se encuentra en la raíz del
proyecto, en la carpeta resource/markdown. Ahí encontraremos lo archivos policy.md y
terms.md, lo que escribamos dentro de estos archivos es lo que se mostrara en las
políticas y condiciones respectivamente.
Alpine
Como resumen podemos decir que tanto JetStream como Breeze instalan Tailwind pero
adicionalmente ambos kits instalar “alpine”.
Alpine es una librería de JavaScript que nos permite agregar interactividad en nuestro sitio
web
window.Alpine = Alpine;
Alpine.start();
Podemos ver que se está importando Alpine y además se está inicializando Alpine
(“window.Alpine = Alpine” y “Alpine.star()”).
Cuando hemos ejecutado la instrucción “npm run build” lo que hemos hecho es crear un
manifiesto que básicamente es compilar todos los archivos
Y toda esa compilación lo coloca dentro de la carpeta “public/build/assets” en 2 archivos
uno para css (terminación .css) y otro para javascript (.js),
Estos archivos (tanto css como js) son archivos minimizados como se muestra a
continuación
Actualmente nuestro alpine se encuentra incorporado dentro del archivo .js (en algún
lugar de todo ese código) y lo mismo para el tailwind, este se encuentra en algún lado del
archivo Css (archivo terminación .css)
Estos archivos se incorporan dentro de nuestras paginas porque cada página tiene las
siguientes directivas
<!-- Scripts -->
@vite(['resources/css/app.css', 'resources/js/app.js'])
@livewireScripts
Por ejemplo, la directiva @vite y las rutas estamos incorporando los assets minimizados
(los que se encuentran en la ruta (public/build/assets)
Con la directiva @livewireStyle incorporamos los estilos de livewire y para incorporar los
scripts de livewire usamos la directiva @livewireScripts
Entonces cada que deseemos incorporar esas tecnologías ya sea alpine, tailwind o livewire
se deben incorporar esas directivas. Por lo tanto, para evitar declararlas en cada pagina
podemos crear una vista plantilla y meter ahí todas esas directivas y solo invocarlos en las
páginas donde queremos ocuparlos.
Dicho lo anterior hay que recalcar que si configuramos JetStream para que trabaje con
BootStrap en vez de tailwind también tenemos que configurar que la paginación trabaje
con Bootstrap (la paginación es cuando en una tabla se muestra en una página web con
varios registros y estos registros por su volumen se divide en varias páginas). Cabe
mencionar que Laravel 8 de forma predeterminada trabaja con Tailwind.
instalación en Laravel 8
Como primer paso vamos a buscar en Google la palabra “jetstrap” el cual nos redirige a la
página del repositorio
https://github.com/nascent-africa/jetstrap
Nos dirigimos a la sección Install Jetstrap y copiamos el siguiente comando para ejecutarlo
en línea de comandos de visual code de nuestro proyecto, esto va a iniciar la instalación
del paquete
composer require nascent-africa/jetstrap --dev
(opcional) Si tenemos instalado JetStream para trabajar con equipo de personas (teams)
utilizar
php artisan jetstrap:swap livewire --teams
Para finalizar la instalación debemos correr las siguientes instrucciones en ese orden
npm install
npm run dev
php artisan migrate
Listo ya solo queda correr el servidor de php (php artisan serve) y probar Jetstream
trabajando con Bootstrap
Usar Bootstrap con JetStream (metodo2 -correcto-) Laravel 9
Este método es tomado de youtube Como instalar Bootstrap 5 en Laravel 9 con Jetstream
y Vite js, "PROCEDIMIENTO CORRECTO"
https://www.youtube.com/watch?v=tdJ3-gUQxSU&t=16s
Se debe haber creado ya el proyecto (laravel 9) e instalado jetstream con todo y base de
datos ya funcional
Ahora abrimos el proyecto en visual code. Abrimos los archivos que necesitamos
configurar (carpeta resource/views/layouts) son los archivos app.blade.app y
guest.blade.php
buscamos el código
const bootsrap = require ('bootstrap')
window.bootstrap = bootstrap
por el siguiente código
import * as bootstrap from 'bootstrap'
window.bootstrap = bootstrap
Realizado los cambios anteriores al código nos vamos línea de comando y escribimos el
siguiente comando
npm install
npm install sass
npm run build
npm run dev
php artisan migrate
Como extra que no se nos debe olvidar al instalar bootstrap en nuestro proyecto de
laravel con jetstream
es que debemos también actualizar la configuración para la paginación
En nuestro proyecto tenemos un archivo (en la raíz del proyecto) llamado vite.config.js. En
este archivo nosotros indicamos cuales son los archivos que queremos se compile
plugins: [
laravel({
input: [
'resources/sass/app.scss',
'resources/js/app.js',
],
En este ejemplo indicamos son 2 archivos los que va a compilar app.css y app.js
Aquí se esta inicializando Tailwind es decir que cuando inicie el proceso de compilación o
cuando tengamos prendido el servidor de Vite, vamos a tener cargado de manera
predeterminada Tailwind
window.Alpine = Alpine;
Alpine.start();
Aquí esta inicializando Alpine y al mismo tiempo esta importando un archivo Bootstrap.js
La pregunta es: ¿una vez que se compilen estos archivos como los incluimos en nuestras
páginas? Esto se hace a través de la directiva @vite que lo tiene los archivos .blade
Por ejemplo, en el archivo app.blade.php (ruta views/layouts/) dentro del head vemos la
directiva
<!-- Scripts -->
@vite(['resources/css/app.css', 'resources/js/app.js'])
Cuando usamos componentes nos permite extraer todo el código necesario para mostrar
el botón en un documento (archivo blade) aparte y posteriormente, cuando necesitemos
utilizar el botón, simplemente hacemos referencia pasándole ciertos parámetros (como
por ejemplo el texto y/o título) a ese componente y tendríamos el botón completo.
La segunda forma para pasar valores mucho más grandes o pasar una estructura
HTML (por ejemplo, alguna etiqueta h1, alguna etiqueta p, algún enlace, etc). Esto
se logra con slots secundarios (recuerden que el mensaje principal lo pasamos
como una variable $slot que sería el slot primario). Es importante definir la
propiedad como name para identificar ese slot en específico (cualquier otra
etiqueta no la reconocerá)
Para esto definimos
<x-slot name=”IdentificadorName”>
Esto es el título desde el slot (o el texto que queramos como título)
</x-slot>
En el archivo código fuente del componente no necesitamos definir la directiva
@props únicamente sustituimos el texto del título que trae como ejemplo por
{{ $ IdentificadorName }}
En la versión laravel 9 se puede definir el segundo slot (en este caso el titulo) se
hace con la sintaxis x-slot:nombre (importante, los 2 puntos tienen que ir pegado a
slot sin espacios, de lo contrario marcara error)
<x-slot:Titulo>
Esto es el titulo de prueba
</x-slot>
Múltiples slots
Se puede definir múltiples slots con la propiedad name como se muestra a continuación
<x-alert>
<x-slot name="Titulo">
Esto es el titulo sin name2
</x-slot>
<x-slot name="valor">
Titulo 2
</x-slot>
<x-slot name="valor2">
Titulo 4
</x-slot>
<p>Cuerpo de texto</p>
</x-alert>
Importante la propiedad name del slot no se necesita definir dentro del código fuente con
la directiva @props.
<div class="bg-orange-100 border-l-4 border-orange-500 text-orange-700 p-4"
role="alert">
<p class="font-bold">{{ $valor2 }}</p>
{{ $slot }}
{{$valor}}
<br>
{{$Titulo}}
</div>
Ahora para cambiar el estilo de acuerdo con el tipo de alerta (valor de type) del
componente lo podemos hacer con una condicional (entre código php) de acuerdo al valor
que trae la variable $type será el estilo CSS que se mostrará.
Para poner código php dentro del archivo blade se hace con la directiva @php @endphp
Entonces el código quedaría
@php
switch($type){
case ‘info’:
$clases = “bg-blue-100 borde-blue-500 text-blue-700”;
break;
case ‘danger’:
$clases = “bg-red-100 borde-red-500 text-red-700”;
break;
default:
$clases = “bg-green-100 borde-green-500 text-green-700”;
break;
}
@endphp
Ahora dentro de la etiqueta HTML imprimimos el valor de $clases.
<article class=”border-1-4 p-4 {{$clases}}” role=”alert”>
El código anterior lo que hará será concatenar lo que ya trae el atributo class con lo que
tiene la variable $clases.
Variable $attributes
Si en el llamado del componente definimos un atributo por ejemplo id ( <x-alert
id=”alerta”> ), pero no lo definimos en la directiva @props (en el archivo donde se define
el código fuente del componente) el atributo id por defecto queda almacenado en la
variable $attribute. Solo aquellos atributos que se definieron en el llamado del
componente, pero no fueron declarados en el código fuente del componente con la
directiva @props serán los que se almacenan en la variable @attibutes
Esta variable al imprimir por ejemplo id=”alerta”, la podemos sustituir en el lugar que le
corresponde dentro de la una etiqueta HTML en el código fuente del componente. Por
ejemplo
<div {{$attributes}} class=”clase1”> </div>
Esto imprimiría <div id=”alerta” class=”clase1”> </div>
Aquí lo que hace el atributo clase es que los combina. Es decir, utiliza el valor definido en
la llamada del componente y además utiliza el valor de class definido en archivo código
fuente del componente.
IMPORTATE solo el atributo class es el que combina, ya que cualquier otro atributo que
este definido en ambos lados (tanto en la llamada del atributo como en el archivo código
fuente del atributo) va a sustituir el valor, predominando únicamente el valor del atributo
definido en la llama del componente.
Es decir si de define el atributo role=”prueba” en la llamada del componente y también se
define el atributo role=”alerta” en el archivo código fuente del componente. El valor que
predomina será role=”prueba”.
Separar código php de la vista (componente de clase)
Para esto tenemos que crear un componente de clase.
Para crear un componente de clase se hace con el comando
php artisan make:component Alert2
Esto crea 2 archivos
El primer archivo lo crea dentro de app/views/Components (aquí se ubica el archivo
Alert2.php). Nota no confunda la carpeta components (ruta resource/views/components)
En el primer archivo vamos a poner toda la logia de php. Dentro de este archivo, en el
método constructor vamos a pasar como parámetro lo que tenía la directiva @props y
dentro del método constructor vamos a pegar el código php
public function __construct($type='info')
{
switch ($type) {
case 'info':
$class="bg-blue-100 border-blue-500 text-blue-700 ";
break;
case 'danger':
$class="bg-red-100 border-red-500 text-red-700 ";
break;
default:
$class="bg-green-100 border-green-500 text-green-700 ";
break;
}
}
namespace App\View\Components;
use Illuminate\View\Component;
class Alert2 extends Component
{
public $clases; <- propiedad publica
/**
* Create a new component instance.
*
* @return void
*/
public function __construct($type='info') <- metodo constructor
{
switch ($type) {
case 'info':
$class= "bg-blue-100 border-blue-500 text-blue-700";
# code...
break;
case 'danger':
$class= "bg-red-100 border-red-500 text-red-700";
# code...
break;
default:
$class= "bg-green-100 border-green-500 text-green-700";
# code...
break;
}
$this->clases = $class;
}
/**
* Get the view / contents that represent the component.
*
* @return \Illuminate\Contracts\View\View|\Closure|string
*/
public function render()
{
return view('components.alert2');
}
}
<div class="py-12">
<div class="max-w-7xl mx-auto sm:px-6 lg:px-8">
{{-- @php
$type = 'danger';
@endphp
namespace App\View\Components;
use Illuminate\View\Component;
El punto importate a resaltar es que jetstream llama a sus plantillas como si fueran
componentes y no a través de la directiva @extends(‘rutaPlantilla’).
30.- Modificando la plantilla de JetStream
Lo que vamos a editar es la vista dashboard que aparece una vez que el usuario se ha
logueado.
Ruta de la plantilla
Primero es identificar los archivos que intervienen. Para identificar el archivo vista
dashboard, nos vamos al archivo web.php dende se definen las rutas (carpera
“routes/web.php”
Route::middleware(['auth:sanctum',
config('jetstream.auth_session'),'verified'])->group(function ()
{
Route::get('/dashboard', function () {
return view('dashboard');
})->name('dashboard');
});
El primero nos dice que en la raíz del sitio web nos va a dirigir a la vista welcome.
El segundo route tiene un middleware
El middleware es como un filtro de la futa, es decir si se cumple la condición del
middleware, entonces nos dirigirá a la vista dashboard, de lo contrario nos dirigira al URL
de login. En este caso el middleware nos indica que la condición a cumplirse es el
logueado exitoso del usuario.
<x-app-layout>
<x-slot name="header">
<h2 class="font-semibold text-xl text-gray-800 leading-tight">
{{ __('Dashboard') }}
</h2>
</x-slot>
<div class="py-12">
<div class="max-w-7xl mx-auto sm:px-6 lg:px-8">
{{-- @php
$type = 'danger';
@endphp
<x-app-layout> indica que se esta llamado un componente (en este caso plantilla). La
instrucción indica lo siguiente:
El llamado de x indica que es un componente
App indica que esta en la carpeta app
layout indica el nombre de componente (nombre del archivo)
Por lo que nos dirigiremos a la carpeta “app/AppLayout.php” el cual nos muestra el
siguiente código:
<?php
namespace App\View\Components;
use Illuminate\View\Component;
Lo importante en este código es que llama a la vista “layouts.app”. esta vista esta ubicada
en la ruta “resources/views/layouts”. Este archivo es la plantilla base que se usaría en las
otras vistas. analizando su código encontramos los siguiente:
<!DOCTYPE html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="csrf-token" content="{{ csrf_token() }}">
@stack('modals')
@livewireScripts
</body>
</html>
El método str_replace tomando el valor que tiene la variable “locate” para asignarlo al
atributo “lang”.
El valor de la variable en este ejemplo tiene valor “en”.
'locale' => 'en',
Esta variable se encuentra en el archivo app.php (en la ruta “config/”).
Este código
<!-- Styles -->
@livewireStyles
Incorpora los estilos de livewire
Defer
En el siguiente código es importante resaltar defer
<!-- Scripts -->
<script src=https://cdn.jsdelivr.net/gh/alpinejs/alpine@v2.7.0/dist/alpine.js
defer></script>
Lo que hace defer es que el código <script src=…> lo pasa al final de justo antes del cierre
de <body>. Con esto permite se ejecute todo el código antes de ejecutarse el script.
Defer lo que indica al navegador es que no espere por el script. En lugar de ello, debe
seguir procesando el HTML, en otras palabras:
los scripts con defer nunca bloquean la página.
Los scripts con defer siempre se ejecutan cuando el DOM esta listo (pero antes del
evento DOMContentLoaded).
<x-jet-welcome/>
Este componente engloba todo el contenido que esta en el recuadro naranja de la imagen
anterior. Lo vamos a sustituir por texto de relleno.
Para crear automáticamente 5 parrafos con texto de relleno uso la siguiente instrucción
P*5>lorem + tab.
@php
$classes = ($active ?? false)
? 'inline-flex items-center px-1 pt-1 border-b-2 border-indigo-
400 text-sm font-medium leading-5 text-gray-900 focus:outline-none
focus:border-indigo-700 transition'
: 'inline-flex items-center px-1 pt-1 border-b-2 border-
transparent text-sm font-medium leading-5 text-gray-500 hover:text-gray-700
hover:border-gray-300 focus:outline-none focus:text-gray-700 focus:border-
gray-300 transition';
@endphp
Analizando el código vemos que recibe un atributo active. Este atributo pasaría un true o
false.
En una variable $classes almacenar una cadena dependiendo si el valor de active es true o
false.
Posteriormente a través de $attribute->merge va a combinar lo que tenga la clase con lo
que se almaceno en la variable @classes.
Posteriormente imprime la variable slot.
<x-jet-nav-link :active="false">
Blog
</x-jet-nav-link>
</div>
Le agregamos la propiedad href para redireccionar a otra pagina (el código fuente del
componente tiene el tag <a> y al imprimir la variable $attribute->merge concatenara la
propiedad href com las demás propiedades que se hayan declarado)
Hay que hacer lo mismo en modo responsivo (mobiles) por lo que buscamos el siguiente
código (esta vez el componente es <x-jet-responsible-nav-link>)
<!-- Responsive Navigation Menu -->
<div :class="{'block': open, 'hidden': ! open}" class="hidden
sm:hidden">
<div class="pt-2 pb-3 space-y-1">
<x-jet-responsive-nav-link href="{{ route('dashboard') }}"
:active="request()->routeIs('dashboard')">
{{ __('Dashboard') }}
</x-jet-responsive-nav-link>
</div>
Por lo tanto, agregar un nuevo link en el menú de navegación se tiene que realizar en las
dos secciones.
<x-jet-nav-link :active="request()->routeIs('blog')">
Blog
</x-jet-nav-link>
</div>
</div>
Aquí es donde se crean los links de navegación. Estos links se crean a través del
componente <x-jet-nav-link>
En este códigoes un arreglo general, que tiene 2 arreglos. Cada arreglo es un link (cada
arreglo tiene su name, su route y su active). En el segundo arreglo (link Prueba) en route
se puso # por que aun no está creada la ruta y lo mismo para active se puse
predeterminado el valor de False ya que no existe aun esa pagina web.
Para el llamado de este componente lo vamos a realizar dentro de un foreach para que
vaya recorriendo arreglo por arreglo y así ir “pintando” cada link.
Este es el código para el menú en pantalla normal
<!-- Navigation Links -->
<div class="hidden space-x-8 sm:-my-px sm:ml-10 sm:flex">
@foreach ($nav_links as $nav_link)
<x-jet-nav-link href="{{ $nav_link['route'] }}"
:active="$nav_link['active']">
{{ $nav_link['name'] }}
</x-jet-nav-link>
@endforeach
</div>
@endforeach
</div>
Para ello abrimos el archivo welcome.blade.php y comentamos todo el código que tiene.
Posterior a eso llamamos al componente que hace uso de la vista app.blade.php. Este
componente está en la ruta “app/view/AppLayout.php” y se llama AppLayout.php. El
componente se llama escribiendo <x-app-layout>
En este código comprimido el tag <div> lo ponemos dentro de la directiva @auth y dentro
de la directiva @else ponemos los links que nos van a redireccionar al login y register. Solo
que para mantener la estética los links se crean con sus componentes <x-jet-responsive-
nav-link>
Para crear un middleware se hace desde la línea de comandos (en la carperta del proyecto
– presionando control + ñ en visual studio code) y escribiendo la siguiente instrucción.
php artisan make:middleware NombreMiddleware
namespace App\Http\Middleware;
use Closure;
use Illuminate\Http\Request;
class CheckAge
{
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure(\Illuminate\Http\Request): (\Illuminate\Http\
Response|\Illuminate\Http\RedirectResponse) $next
* @return \Illuminate\Http\Response|\Illuminate\Http\RedirectResponse
*/
public function handle(Request $request, Closure $next) //<-- Metodo
encargado de filtrar las solicitudes
{
return $next($request);//<--codigo que permite acceda URL solicitado
}
}
Lo que es importante aquí es resaltar que lo que se ponga (codifique) dentro de la función
es lo que será la condicionándote para saber si se toma una acción u otra acción (con un if
por ejemplo). Aquí mostramos un código que tiene 2 returns pero el primero esta
comentado. Se podría usar un if para determinar que return tomar
public function handle(Request $request, Closure $next)
{
// return $next($request);//<-- Este es el que permite acceda al URL
solicitado
return redirect('/');
}
Registrar el middleware
Una vez creado el middleware es obligatorio registrarlo para poder usarlo. Esto es para
que Laravel reconozca que esta clase en particular (en el ejemplo CheckAge) su trabajo
será filtrar las solicitudes HTTP.
Esto se registra en la parte final del archivo “kernel.php” (ubicado en la ruta “app/Http”).
Ahí buscamos el siguiente código
protected $routeMiddleware = [
'auth' => \App\Http\Middleware\Authenticate::class,
'auth.basic' => \Illuminate\Auth\Middleware\
AuthenticateWithBasicAuth::class,
'auth.session' => \Illuminate\Session\Middleware\
AuthenticateSession::class,
'cache.headers' => \Illuminate\Http\Middleware\
SetCacheHeaders::class,
'can' => \Illuminate\Auth\Middleware\Authorize::class,
'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class,
'password.confirm' => \Illuminate\Auth\Middleware\
RequirePassword::class,
'signed' => \App\Http\Middleware\ValidateSignature::class,
'throttle' => \Illuminate\Routing\Middleware\
ThrottleRequests::class,
'verified' => \Illuminate\Auth\Middleware\
EnsureEmailIsVerified::class,
];
return redirect('/');
}
Este método lo que hace es interceptar la solicitud Http (URL) y de acuerdo a lo que
definamos dentro del método realiza una acción o realiza otra acción. Por ejemplo el
siguiente código
public function handle(Request $request, Closure $next)
{
if ($request->age >=18) {
return $next($request);
} else {
return redirect(no-autorizado);
}
}
Route::get('no-autorizado', function () {
return "Usuario no autorizado";
});
De esta manera esta ruta tiene que cumplir con los 2 middleware para que se muestre el
return “Has accedido correctamente a esta ruta”. De esta manera si el usuario no esta
registrado ya no sale el error de querer leer un atributo de un usuario que no esta
registrado, lo que hace en cambio es redireccionar a la URL de login y si inicio sesión ahora
si me redirecciona al URL prueba y me muestra el contenido de return.
return "<strong>Has accedido correctamente a esta ruta.</strong>";
El diagrama entidad-relacion indica que dentro de las reglas del negocio debo
encontrar entidades. Entiéndase entidades como objetos ya sean reales o
conceptuales que tengan atributos.
Estas relaciones las especificamos en una especie de rombo dando clic al icono y lo
colocamos entra las entidades como se muestra a continuación.
Luego lo unimos con una pequeña línea con el icono. Dando clic en el centro de la entidad
En este ejemplo seria la entidad Users como mínimo puede tener 0 perfiles de creadores,
ya que puede existir el caso que ningún usuario sea creador y como máximo la entidad
Users tendría 1 perfil de creador ya que un usuario si puede tener un perfil de creador.
En modo inverso (cardinalidad a izquierda) seria un creador puede estar asignado mínimo
a un usuario y un creador solo puede estar asignado máximo a N usuarios
Teniendo las cardinalidades ahora damos clic en el icono texto y escribimos arriba
del rombo (la relación) el máximo de cada lado de la cardinalidad
Clave primaria
Esto es uno de esos atributos de esta entidad va a ser una clave primaria. Con esto quiere
decir que esa entidad tiene que ser única e irrepetible entre los atributos. Como por
ejemplo el Email. Sin embargo, algunas ocasiones será imposible encontrar un atributo de
valor único e irrepetible por lo que podemos usar un nuevo atributo de nombre ID y se le
conoce como clave primaria sintética.
El atributo etiquetas es doble por que la reglas de negocio indica los siguiente
Los Post deben tener portada, titulo, descripción, categoría y pueden tener uno o más
etiquetas. Es decir que pueden tener varias etiquetas y por ende tiene sub valores. Como
que etiqueta es (color y definición).
Entidades detectadas
Usuarios – Atributos: nombre, email, dirección.
Rol -Atributos: Id, Nombre.
Perfil – Atributos: Biografía, titulo, sitio web.
Post – Atributos: Categoría, titulo, body.
Comentarios – Atributos: Mensaje, usuario que lo escribió.
Video – Atributos: Titulo, descripción, URL.
Etiquetas – Atributos: Id, Nombre.
Imágenes – Atributos: Tipo de imagen
Relación 1 a 1
Tenemos el siguiente diagrama
Para crear una relación de 1 a 1 en MySQL WorkBench debemos primero crear las dos
entidades (usuarios y perfiles) con sus respectivos atributos.
Para poder crear la relación de uno a uno hay que agregarle un campo más a la tabla
Profiles. Este nuevo campo tendrá como característica que será una llave foránea de la
tabla Users.
Con para explicar la llave foránea veamos las siguientes tablas
Para poder hacer la relación a la tabla Profiles se le agrego un nuevo campo (user_id). Este
nuevo campo tendrá 2 condiciones, será una llave foránea de la tabla Users y además
tendrá se definirá como valor único (es decir que no puede repetir su valor).
La llave foránea en un campo sirve para que ese campo pueda ingresar valores que han
sido definidos como llave (id) de una tabla. Es decir, la tabla User tiene como llave los
valores 1,2,3 por lo que si en el campo User_id de la tabla Profiles trataran de poner un
valor 4 este no lo permitiría. En otras palabras, una restricción de llave foránea significa
que los únicos valores que puede ingresar corresponde a los valores de la llave primaria de
otra tabla.
La convención de Laravel dicta que los Id deberán de ser en singular por lo que
deberíamos de editar el nombre users_id por user_id.
Relación 1 a muchos
Esta relación es exactamente igual a la relación 1 a 1 explicada en el capítulo anterior
(relación 1 a 1), la diferencia es que el campo adicional requerido (user_id) para hacer la
relación únicamente se le asignará la llave foránea y permitir que se puedan repetir
registros, es decir no se activara la casilla UQ (unique).
La convención de Laravel dicta que los Id deberán de ser en singular por lo que
deberíamos de editar el nombre users_id por user_id.
Usando la convención de Laravel, indica que deberá usarse ambos nombres (el nombre de
cada tabla) y combinarlos, además de ir en singular. Esta combinación deberá ser en
orden alfabético. Por ejemplo si tenemos la tabla Users y la tabla Roles el nombre de la
tercera tabla deberá ser Role_User.
Para crear la relación de muchos a muchos en MySQL WorkBench damos clic en el icono
Para ello primero damos clic en la tercera tabla y luego en la tabla que deseamos hacer la
relación (tabla1) con esto se crea el primer campo como llave foránea (id_tabla1).
Repetimos la operación, dar clic en la tabla 3 para luego dar clic en segunda tabla que
hacemos la relación (tabla 2) y con esto se crea el segundo campo (id_tabla2)
Relación polimórfica 1 a 1
Las relaciones polimórficas son aquellas donde 3 tablas se relacionan. Por ejemplo, en el
siguiente diagrama conceptual se tienen 3 entidades (tablas que se van a relacionar):
Usuarios, Imagen y Post.
La relación de usuarios a imagen es de 1 a 1.
La relación de Post a Imagen también es de 1 a 1.
Para poder relacionar estas 3 tablas, vamos a utilizar la tabla que tienen en común estas 3
tablas. En este ejemplo la tabla en común es la tabla imagen.
Para poder hacer la relación necesitamos realizar 3 pasos.
1. A la tabla Imagen además de sus campos (id, URL) le agregamos 2 campos más:
a. Imageable_id . este campo hará la relación de esa fila ya sea con la tabla
usuarios o la tabla Post. Por ejemplo, asumiendo que el primer y segundo
registro de esta tabla tengan el valor 1
b. Imageable_type. En este campo lleva por valor el nombre del modelo
encargado de administrar la tabla, ya sea la tabla1 o la tabla2. En este
campo es el que indica de quien es el id de imageable_id.
En esta última imagen indicamos que el registro 1 de la tabla IMAGES en el campo
imageable_id pertenece a la tabla User y el segundo registro de la tabla Images pertenece
a la tabla Post.
Para crear este diagrama en MySQL WorkBech primero necesitamos crear las 3 entidades.
En el caso de la entidad (tabla 3) que es la tabla en común cuando se creen los campos
imageable_id e imageable_type se marcan ambas se marcan como llave primaria y listo.
Lo que nos queda como un registro
Para crear el diagrama modelo lógico en Mysql Workbench es primero creamos las dos
tablas principales y posteriormente creamos la tabla que será la que hará la relación. Esta
tabla que es la relación se crean los campos commnetable_id y Commentable_type
En este caso tampoco se utilizan los iconos del menú de la izquierda ya que no
podemos crear una llave foránea puesto que el campo commentable_id tiene que
permitir valores tanto de la tabla Post como de la tabla videos.
Como la columna tag_id (de la tabla taggables) hace relación únicamente a la columna id
de la tabla Tags, entonces si podemos definir la columna tag_id (tabla taggables) como
llave foránea de la tabla Tags.
Para crear el diagrama modelo en MySQL WorkBench primero creamos las 4 tablas
requeridas. Recuerde que la cuarta tabla será la que la que hará de pivote entre las 3
tablas por lo que tendrá los campos id – llave primaria, taggable_id y taggable_type.
Creada las tablas damos clic en el icono para crear la relación de uno a muchos entre
la tabla Tags y la tabla Taggables. Primero damos clic donde ira el campo que tendrá la
llave primaria y posteriormente damos clic en la tabla que será la referencia.
En el siguiente capitulo vamos a ver un paso más que es el de normalización.
Entonces cuando tengamos un campo compuesto, la primera forma normal nos indica que
debemos desdoblarlo como se muestra en la siguiente imagen.
En vez del campo dirección, este se dividió en más campos como calle, numero, distrito,
ciudad.
Otra opción es que el campo dirección lo hubiéramos creado en otra tabla (como un
catálogo) y en la tabla users le pongamos el campo id_direccion como llave primaria de la
tabla dirección y que sea una relación de uno a uno.
2da forma normal
Esta segunda forma normal no indica que
1. Nuestras tablas ya deben tener la 1ra forma normal
2. Debe existir una dependencia funcional completa de todos los campos de una
tabla con su clave primaria. Este punto vigila que no haya redundancia de
información.
Para explicar el punto 2 observemos las siguientes tablas
De esta forma aun sabremos que mensaje le pertenece a que usuario, además no
tenemos redundancia de información y lo mas importante ahora si todos los campos (sus
registros) tienen una dependencia funcional completa con respecto a la llave primaria
(campo id).
El punto 2 de la tercera forma normal nos dice que cada campo debe depender
enteramente del campo id (llave primaria). Es decir, el campo name (el articulo) ese
registro únicamente depende del campo id. Pero si observamos el campo categoría
depende directamente de que articulo se haya puesto (es decir depende del campo name
y el campo body) ya que si el articulo habla de muebles no podría llevar una categoría
desarrollo web o diseño web.
Explicado de otra manera el campo categoría si tiene una relación con el campo id pero no
es una relación directa. La relación directa del campo categoría es con el campo name y el
campo body.
Empecemos por abrir nuestro proyecto en visual Studio code ( o podemos crear uno
nuevo con Jetstream)
Para crear la tabla de profiles se abre la terminal de visual code (esto en nuestro proyecto
laravel) y escribimos el siguiente comando
$table->timestamps();
});
}
En el siguiente capitulo se explica insignedBigIntener() y el método foreing()
Como podrán observar el campo id se crea con el método id(). Este método di() establecer
por defecto los valores como entero grande sin signo y ende el campo user_id que vamos
a crear deberá de llevar la restricciones de bigInteger, unsigned y solo permita valores
únicos (no repetidos). Recuerde que es una relación de uno a uno.
$table->unsignedBigInteger('user_id')->unique();
Definido el campo user_id el siguiente paso es decirle que este campo tendrá una
restricción de llave foránea de la siguiente manera:
$table->foreign('user_id')->references('id')->on('users')-
>onDelete('cascade');
De esta manera se especifica que user_id será llave foránea (foreing) en referencia al
campo id (references) de la tabla users (on).
El método onDelete(). Se establece para definir que acción tomar en caso que se elimine
un registro de la tabla users y este relacionado con un registro de la tabla profile. Este
metdoTiene dos funciones:
cascade, si se borra un registro de la tabla users y este usuario tiene un registro
(esta relacionado) con un regstro de la tabla profiles, al borrar al usuario (registro
de la tabla users) también se borraría el registro que tiene relación con este
usuario en la tabla profles.
set null: Al eliminar un registro de la tabla users (eliminar un usuario) el o los
registros que tengas relación con este usuario en la tabla profile se definirían como
valor nulo. Para este registro hay que definir que este campo permita valores nulos
con el método nullable()
$table->unsignedBigInteger('user_id')->unique()->nullable();
Un ejemplo de cuando usar set null es por ejemplo que si se elimina un usuario de
la base de datos y este usuario a escrito artículos, al eliminar el usuario quisiera se
sigan conservando sus escritos y mostrándolos en la sección de los artículos, por
ende debería de establecer este valor como set null, así al eliminar el usuario sus
escritos seguirán conservándose en la base de datos.
Creando el archivo model
Podemos crear el archivo migrate y model en una sola línea creando el archivo model de
la siguiente manera con un sufijo que el que va a crear el archivo migrate.
Note que se puede escribir el nombre del modelo en Mayúscula la primera letra. Esto va a
crear el archivo Profile.exe en la carpeta “app/Models”.
Una vez creado el archivo artisan migrate lo ejecutamos para que se cree la tabla en la
base de datos con el siguiente comando en línea de comando de visual Code
php artisan migrate
En caso de error de conexión es importante que haya definido las credenciales de acceso
así como el nombre de la base de datos en el archivo .env en la raíz del proyecto.
¿cómo puedo hacer para que cuando recupere el registro de un usuario también
tenga acceso al registro de la tabla profiles relacionado con ese usuario?
Como recordaran se hizo una relación de uno a uno de la tabla usuarios a la tabla profiles,
donde la tabla profiles tiene un campo llamado user_id la cual es una llave foránea de la
tabla user_id.
Para poder acceder a al registro que esta relacionado con el usuario que acabamos de
obtener su registro debemos recordar que eloquen trata cada registro como si fuera un
objeto. Un objeto que es instanciado de su modelo.
Primero hay que recordar que “eloquen” trata cada registro (consulta) como si fuera un
objeto y este objeto es una instancia de su modelo (el modelo designado para trabajar la
una tabla en específico). Por lo tanto:
Abrimos el modelo de la tabla 1 el cual en este ejemplo es el modelo User y al final del
código (dentro de la clase) le vamos a agregar un nuevo método el cual vamos a darle el
nombre de profile
public function profile()
{
}
Como ejemplo dentro del método vamos a meter manualmente el código para recuperar
el registro.
donde foreing_key es el nombre del campo que es la llave foranea (tabla profiles) y el
local_key es el nombre del campo id(tabla Users).
Donde en la variable user vamos a llamar al modelo User y a su método find. En esta
ocasión podemos usar el método find ya que vamos a realizar la búsqueda por el id y le
pasamos como parámetro justamente ese id que en este caso lo esta almacenando
user_id.
Existe un código mas simplificado para obtener un registro uno a uno en el proceso
inverso (es decir al acceder al registro de la tabla profiles obtenemos simultáneamente los
registros de la tabla users).
El método belongsTo() da por echo que la llave foranea es user_id y la llave priemara de la
tabla users se llama Id. En caso contrario hay que pasar como segundo parámetro el
nombre de la llave foranea y como tercer parámetro el nombre del campo llave (tabla
Users).
Ahora para acceder a la información del perfil (tabla profiles) se hace de la siguiente
manera:
$user->profile + enter (no lleva ; )
Haciendo el proceso contrario ahora obteniendo primero el registro de la tabla Profile y
luego accediendo al registro de la tabla Users relacionado con el registro profile
Ahora obtenemos el registro de la tabla users relacionado con este perfil (tabla Profile)
Es importante comentar que accedemos al registro como una propiedad de ese objeto (al
escribir $profile->user es como si fuera una propiedad) sin embargo user se definió como
un método dentro de la clase del modelo.
Esto ocurre ya que el método belongTo() y el método hasOne() al ejecutarse genera
propiedades dinámicas. Es decir, le está agregando de manera dinámica la propiedad user
al modelo Profile y la propiedad profile al modelo user. Esto lo hace así por un tema de
eficiencia ya que al recuperar el registro automáticamente se carga la información de
todas sus relaciones en forma de propiedades y de esa manera no tenemos que esperar a
ejecutar un método para que empiece a obtener esos registros.
Por eso es importante usar los métodos que nos proporciona Laravel para generar las
relaciones y no hacerlo con las consultas “manuales”.
En este ejercicio vamos a crear el siguiente diagrama. En este diagrama es una relación de
uno a muchos, de la cual la tabla users y la tabla categorías son entidades fuertes y la tabla
post es una entidad débil. Es decir 2 tablas van a conectarse con una tercera tabla.
Primero se van a crear las entidades fuertes (tabla users y tabla categorías)
Creamos la entidad débil (tabla post), en esta entidad como observamos en el diagrama se
crean dos campos user_id y categorías_id que servirán como llaves foráneas.
Por ultimo creamos las relaciones
Para crear la tabla categorías se debe crear los archivos migration y los archivos models (la
tabla migration crear la tabla física en la base de datos y el archivo model es el encargado
de administrar la tabla).
Para crear los archivos en una sola línea de comando se escribe lo siguiente (recuerde que
el archivo model se crea en singular.
Esto creará el archivo modelo y al mismo tiempo creará el archivo migrate con el siguiente
nombre create_categorias_table
Creacion del archivo model y al mismo tiempo otros archivos (factory, seeder, controller,
etc)
Si además de la migración necesitamos que se cree un controlador escribimos
Si quisiéramos que nos cree todos los anteriores (model, migrate, controlador,seede,
factory) poneos a de all.
$table->string('name');
$table->text('body');
$table->unsignedBigInteger('user_id')->nullable();
$table->unsignedBigInteger('categoria_id')->nullable();
$table->foreign('user_id')->references('id')->on('users')
->onDelete('set null');
$table->foreign('categoria_id')->references('id')
->on('categorias')->onDelete('set null');
$table->timestamps();
});
}
Para ello abrimos el archivo modelo de la tabla 2 (ejemplo users.php ubicado en la ruta
app/Models/user.php) y creamos el método post (dentro de la misma clase). Para
recuperar todos los registros de este usuario usamos el método “hasMany”
Recuperamos los registros de la tabla Post que estén relacionados con el usuario cuyo id
es 1. Recuerde que aunque el Posts es un método accedemos a este como si fuera una
propiedad. (en el capitulo anterior se explico el por que se crean estas propiedades
dinámicas por tema de eficiencia)
$user->posts:
La convención dicta que para la creación de la tabla que hace la relación entre las otras 2
tablas tiene que llevar por nombre las siguientes reglas:
singular,
minúsculas,
orden alfabético.
Es decir, si la tabla 1 se llama users y la tabla 2 se llama roles, la creación de la tabla 3
debe llevar por nombre role_user (la r esta antes de la s). Esta tercera tabla tiene dos
campos: user_id y role_id
El campo user_id debe ser llave foránea de la tabla Users (campo id) y el campo role_id
debe ser llave foránea de la tabla roles (campo id). Ambos campos (user_id y role_id)
permiten duplicidad de datos.
En caso de que aún no se haya creado la tabla 2 (roles) creamos su archivo modelo y su
archivo migración
php artisan make:model Role -m
Algo por resaltar es que al crear una tabla se crea su migración y su archivo modelo, pero
cuando es una tabla intermedia entre 2 tablas, la tercera tabla no se crea el archivo
modelo solo su archivo migración. Solo se usaran los archivos modelos de las tablas 1 y 2.
Por ende solo se crear el archivo migrate de la tabla 3
php artisan make:migrate create_role_user_table
El archivo migration para esta tercera tabla tendrá el siguiente código en su función up()
public function up()
{
Schema::create('role_user', function (Blueprint $table) {
$table->id();
$table->unsignedBigInteger('role_id');
$table->unsignedBigInteger('user_id');
$table->foreign('role_id')->references('id')->on('roles')-
>onDelete('cascade');
$table->foreign('user_id')->references('id')->on('users')-
>onDelete('cascade');
$table->timestamps();
});
}
El método foreing indica que el parámetro que se le pase será una llave foránea
El método reference indica que será llave foranera del campo llamado “id”
El método on, indica en su parámetro la tabla a la que pertenece el campo que se indica
en el método reference.
El método onDelete, indica que acción se realizara en caso de que se borre un registro de
la tabla externa donde se hace referencia. Tiene dos posibles valores
Cascade indica eliminar igual este registro
set null indica que se ponga como valor null. Si se esoje esta opción se debe indicar
que este campo aceptara valores nulos con el método nullable()
$table->unsignedBigInteger('role_id')->nullable();