Carpetas de esta lección
  • resources/views
  • Http/Controllers
  • resources/views/layout

Primera parte: uso de vistas

Para mostrar código HTML, debemos crear unos documentos llamados vistas. Hasta ahora estamos devolviendo sólo frases.

Vamos a resources/views y creamos un archivo llamado home.php. También crearemos una carpeta dentro llamada «cursos» donde estarán las vistas de cada una de las URL de los cursos, que son 3. Por convención, al archivo de cada vista lo nombraremos igual que a cada método invocado en las rutas.

Atajo de teclado: dentro de cada uno de estos archivos php escribimos en Visual Studio Code un signo de exclamación y pulsamos enter, para que se autocomplete con todo el código HTML básico para un archivo con Doctype HTML y los tags mínimos imprescindibles para un archivo de este tipo (html, head title y body).

Vamos al archivo HomeController, y tomamos la frase que devolvemos dentro del método para pegarla dentro de un tag h1 dentro del body de home.php. Luego, escribimos el método view dentro del invoke de HomeController. No es necesario especificar que el archivo que estamos lamando es un archivo php. Queda la clase así:

class HomeController extends Controller
{
    public function __invoke(){
        return view("home");
    }
}

Y el archivo home.php así:

<!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>Document</title>
</head>
<body>
    <h1>Bienvenido a la página principal</h1>
</body>
</html>

Hacemos esto mismo para CursoController, modificando también cada una de las vistas (añadiendo las frases dentro de h1 como en el caso de home.php), y dejamos su código así:

class CursoController extends Controller
{
    public function index(){
        return view("curso.index");
    }

    public function create(){
        return view("curso.index");
    }

    public function show($curso){
        return view("curso.show");
    }
}

Lo primero, notamos que ahora estamos especificando la ruta de cada vista, mediante un punto: curso.index, curso.create y curso.show.

Las dos primeras vistas están perfectas, pero debemos hacer algo con la variable $curso del método show(). No basta con escribir la variable dentro de la vista show como sigue:

(...)
<body>
    <h1>Url con la variable <?php echo $curso?></h1>
</body>
(...)

Porque Laravel nos arrojaría un error diciendo que la variable no está definida dentro del método. Definimos la variable dentro de un array (entre corchetes:

 public function show($curso){
        return view("cursos.show", ['curso' => $curso]);
    }

Si le pusiéramos otro nombre a la variable, como por ejemplo «alfa», la rescataríamos dentro de la vista con ese nombre:

 public function show($curso){
        return view("cursos.show", ['alfa' => $curso]);
    }

Cuando tenemos intención de pasarle una variable a la vista que coincide con el nombre que estoy recibiendo podemos usar compact() así:

    public function show($curso){
        // return view("cursos.show", ['curso' => $curso]);
        return view("cursos.show", compact("curso"));
    }

Plantillas

Vamos a reciclar todo el código HTML que se repite dentro de cada vista usando plantillas con el motor blade. Primero, vamos a una de las vistas y añadimos algunos comentarios que se reemplazarían por código HTML que también se usaría en otras vistas:

<!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>Home</title>
    <!-- favicon -->
    <!-- estilos -->
</head>
<body>
    <!-- header -->
    <!-- nav -->
    <h1>Bienvenido a la página principal</h1>
    <!-- footer -->
    <!-- script -->
</body>
</html>

Atajo de teclado de Visual Studio Code: si escribimos una línea, la seleccionamos y pulsamo [CTRL] + K, después pulsamos [CTRL] + C para comentar y [CTRL] + U para descomentar.

Creamos la carpeta layout dentro de views, y dentro el archivo plantilla.blade.php. La extensión blade.php es necesaria. Para el contenido que queremos que varíe dentro de cada platilla, usaremos @yield(«nombre identificativo del contenido»). La plantilla queda así:

<!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('title')</title>
    <!-- favicon -->
    <!-- estilos -->
</head>
<body>
    <!-- header -->
    <!-- nav -->
    @yield('content')
    <!-- footer -->
    <!-- script -->
</body>
</html>

Vamos con la vista home.php. En primer lugar, renombramos el archivo como home.blade.php. Luego añadimos un @extends al comienzo de la vista para hacer referencia a la plantilla. Además, usaremos @section para especificar el contenido que cambia dentro de cada vista. Usaremos @section de dos formas, una con una sola línea de código y otra que permite varias líneas de código. La vista home.blade.php queda de la siguiente manera:

@extends('layouts.plantilla')

@section('title', 'Home')

@section('content')
    <h1>Bienvenido a la página principal</h1>
@endsection

Inspeccionando el HTML de esta página vemos que el title es «Home» yq ue el contenido está dentro del body, a su vez dentro de un h1, como especificamos en el @section.

Antes de continuar con todas las vistas, podemos instalar la extensión Laravel Blade Snippets para colorear el có´digo de blade y además autocompletarlo.

Hacemos lo propio con cada una de las vistas, pasando el título y el contenido de cada una con @section, luego de extender la plantilla. También renombramos cada archivo con la extensión blade.php. Ojo con la vista que contiene una variable, show.blade.php, cuya sección content quedaría mejor así, con la doble llave para pasar la variable (nótese también la doble llave para comentar código):

@extends('layouts.plantilla')
@extends('layouts.plantilla')

@section('title', 'Página con variable')

@section('content')
    {{-- <h1>Url con la variable <?php echo $curso?></h1> --}}
    <h1>Url con la variable {{$curso}}</h1>
@endsection

Recursos

Enlace de Youtube: https://www.youtube.com/watch?v=KZGHCSIb9Q0&list=PLZ2ovOgdI-kWWS9aq8mfUDkJRfYib-SvF&index=6

Podemos agrupar las rutas que hemos creado, ya que las tres usan el mismo controlador., Para ello, usaremos el método group().

Cambiaremos este código:

Route::get('/', HomeController::class);

Route::get('cursos', [CursoController::class, 'index']);
Route::get('cursos/create', [CursoController::class, 'create']);
Route::get('cursos/{curso}', [CursoController::class, 'show']);

Por este otro:

Route::get('/', HomeController::class);

Route::controller(CursoController::class)->group(function(){
    Route::get('cursos','index');
    Route::get('cursos/create','create');
    Route::get('cursos/{curso}','show');
});

Así el código queda mucho más limpio. Esta es una característica de Laravel 9.


Recursos

Enlace de Youtube: https://www.youtube.com/watch?v=srDHQLqbwwk&list=PLZ2ovOgdI-kWWS9aq8mfUDkJRfYib-SvF&index=5

En esta lección aprenderemos a usar y crear controladores. Sacaremos la lógica del archivo app.php y dejaremos escrito varios fragmentos de código según la convención de nombres de variables y métodos, creando controladores para tal fin. Es muy importante conocer la convención de la nomenclatura.

Archivos que vamos a investigar en esta lección
  • routes/web.php
  • app/Http/Controllers
Consideraciones
  • Los controladores en versiones anteriores se llaman de otra forma
  • Hemos instalado otra extensión de Visual Studio Code, llamada php Intelephense, que autocompleta nombres de controladores y resalta errores en el código (entre otras cosas)
Crear controladores

Un controlador será un archivo php que tenemos que crearlo en la carpeta app/Http/Controllers. Podemos crearlo manualmente, y también desde la terminal.

php artisan make: controller HomeController

Desde la terminal de Git Bash, navegaremos hasta la carpeta del proyecto y escribiremos el siguiente código para crear un controlador de nombre HomeController. Los nombres se escriben así por convención. Al hacerlo así, desde la terminal y con Artisan, se nos escribe el código que necesitamos para empezar.

php artisan make: controller HomeController

El archivo empieza con el namespace, y nos centraremos en la clase HomeController que se ha creado, donde escribiremos el método.

Usar controladores

En el archivo web.php escribiremos la línea que se refiere al controlador que vamos a usar:

use App\Http\Controllers\HomeController;

Nuestra ruta para la home ahora debe quedarse así, sustituyendo la función por el uso del controlador:

Route::get('/', HomeController::class);

Y el controlador HomeController:

class HomeController extends Controller
{
    public function __invoke(){
        return "Bienvenido a mi proyecto de Laravel";
    }
}

Ya podemos visitar la home con el navegador y ver el mensaje «Bienvenido a mi proyecto de Laravel». Nótese que hemos nombrado a la función __invoke. Esto se escribe así por convención, tanto el hecho de que comience con dos guiones como el nombre del método.

Resumen de lo anterior
  • Creamos el controlador vacío con la consola usando el comando de artisan, respetando la convención de los nombres.
  • En routes/web.php, llamamos al controlador con use
  • Quitamos la función de la ruta de la home y llamamos al controlador usando el método class
  • En el archivo HomeController creado, escribimos el mensaje de bienvenida dentro de la clase del controlador con una función pública llamada __invoke(). Si no se especifica ningún nombre de método, el método de la calse será el método __invoke (lo tenemos en cuenta como concepto para la continuación).
Seguimos creando controladores

Mirando atentamente el siguiente código de web.php, vemos que todos tienen que ver que la URL comienza con la palabra «cursos». Para ello crearemos un único controlador para administrar el código que se muestra más abajo. Comentaremos todas las rutas y nos quedaremos con estas:

Route::get('cursos', function () {
    return "Bienvenido a la página de cursos";
});

Route::get('cursos/create', function () {
    return "Inserción de formulario";
});

Route::get('cursos/{curso}', function ($curso) {
    return "Url con la variable $curso";
});

Podemos crear el controlador desde la terminal de Visual Studio Code, con el comando que hemos usado antes. Ahora nombraremos nuestro controlador como CursoController, en singular por convención, y usando las mayúsculas como hemos hecho antes:

php artisan make:controller CursoController

Usaremos los siguientes nombres de los métodos: index, create y show. El método __invoke se usa solamente para una única ruta, en este caso tenemos tres. Como cada una de ellas está destinada a mostrar una cosa en particular (un índice, un formulario y algo de contenido) usamos estos tres nombres. Son nombres usados (de nuevo) por convención, aunque podríamos usar los que queramos. Nuestra clase «vacía» estará de la siguiente manera:

class CursoController extends Controller
{
    public function index(){

    }

    public function create(){

    }

    public function show(){

    }
}

Pondremos dentro de cada método cada uno de los mensajes que nos retornaba cada ruta. Como vemos en el código, la variable $curso está ahora dentro del método $show:

class CursoController extends Controller
{
    public function index(){
        return "Bienvenido a la página de cursos";
    }

    public function create(){
        return "Inserción de formulario";
    }

    public function show($curso){
        return "Url con la variable $curso";
    }
}

Y ya en web.php para usar el método con nuestras rutas:

use App\Http\Controllers\CursoController;

Para llamar a cada uno de los métodos de CursoController (index, create y show) no podemos llamar sólo al controlador, pues esto buscaría el método __invoke (y este controlador no tiene tal método). Así que le pasaremos en un array, entre corchetes, el nombre del controlador con ::class y el nombre de cada método entre comillas, y las rutas quedarían como sigue:

Route::get('/', HomeController::class);

Route::get('cursos', [CursoController::class, 'index']);

Route::get('cursos/create', [CursoController::class, 'create']);

Route::get('cursos/{curso}', [CursoController::class, 'show']);
Resumen
  • Hemos creado otro controlador, esta vez con tres funciones, cuyos nombres se usar así por convención, según lo que hace cada uno
  • Podemos crear controladores también desde la terminal de Visual Studio Code
  • A la hora de usar el controlador desde el archivo de rutas, lo hemos llamado tres veces (uno por cada ruta) usando un array para llamar a cada uno de sus métodos.

Recursos

Enlace de Youtube: https://www.youtube.com/watch?v=0YxgCH2R2bE&list=PLZ2ovOgdI-kWWS9aq8mfUDkJRfYib-SvF&index=4

Archivos que vamos a investigar en esta lección
  • routes/web.php

Con Laravel no vamos a crear un archivo php por cada página de nuestra web, sino que vamos a usar el FrontController, el patrón en el que se basa Laravel.

Tendremos sólo un archivo de entrada en nuestra aplicación, el index.php. Los archivos a los que el usuario puede acceder están en la carpeta public. Esto se hace por motivos de seguridad, para que no pueda acceder a otros más sensibles.

Laravel sabe qué información debe mostrar cuando un usuario escribe una URL. El archivo que se encarga de administrar las rutas está en la carpeta routes y se llama web.php.

Vemos el contenido de este archivo: aquí Laravel devuelve la vista welcome cuando el usuario pide la ruta principal, que sería localhost/blog/public, por eso en el primer parámetro de gert se indica simplemente un slash:

Route::get('/', function () {
    return view('welcome');
});

Si cambiamos el fragmento anterior por el que sigue, obtendremos sólo la frase al visitar la URL:

Route::get('/', function () {
    /*return view('welcome');*/
return "Bienvenido a mi proyecto de Laravel";
});

Si añadimos un fragmento como el que sigue, estaremos añadiendo una ruta para la URL «cursos» que mostrará el contenido «Bienvenido a la página de cursos». Usamos de nuevo Route::get() con parámetros personalizados. Para ver este contenido, accederemos a la ruta localhost/blog/public/cursos:

 Route::get('cursos', function () {
    return "Bienvenido a la página de cursos";
});

Dejamos esta ruta también para utilizarla en la lección siguiente:

Route::get('cursos/create', function () {
    return "Inserción de formulario";
});

Introduzcamos variables para «subrutas»: basta con utilizar de nuevo Route::get() añadiendo una variable la la función (nótese que en el primer parámetro de get la variable se encuentra entre corchetes):

Route::get('cursos/{curso}', function ($curso) {
    return "Url con la variable $curso";
});

Para probar esta nueva función, visitemos las siguientes direcciones:

  • http://localhost/blog/public/cursos/personalizada
  • http://localhost/blog/public/cursos/variable
  • http://localhost/blog/public/cursos/con una variable
  • http://localhost/blog/public/cursos/que me apetece

En este punto deberíamos instalar Laravel Snippets, la extensión de Visual Studio Code para hacer esta tarea repetitiva más rápidamente (se indica aproximadamente en el minuto 8 del vídeo).

Prestemos atención un momento a este fragmento para crear una ruta, donde vamos a pasar más de una variable para una ruta:

Route::get('nuevaruta/{subruta}/{otrasubruta}', function($subruta, $otrasubruta) {
    return "Estamos en la ruta $subruta y en la subruta $otrasubruta";
});

Los dos últimos fragmentos de código son bastante parecidos. Nuestro código podría interpretar la «otrasubruta» como una variable opcional, y así lo vamos a expresar:

Route::get('nuevaruta/{subruta}/{otrasubruta?}', function($subruta, $otrasubruta = null) {
    if ($otrasubruta) {
        return "Estamos en la ruta $subruta y en la subruta $otrasubruta";
    }
    else {
        return "Estamos en la ruta $subruta";
    }
});
  • Una de las dos variables de get tiene un signo de interrogación al final, indicando que la variable es opcional: la variable $otrasubruta.
  • Ésta ha sido inicializada en la función con valor null
  • Luego, hemos escrito un condicional que comprueba si la variable ha sido o no inicializada, y muestra un mensaje distinto según cada caso.

De esta forma podemos acceder a localhost/blog/public/nuevaruta/algo y también a localhost/blog/public/nuevaruta/algo/otracosa. O también, por ejemplo, a localhost/blog/public/nuevaruta/categoria y también a localhost/blog/public/nuevaruta/categoria/subcategoria.

Este condicional debería estar en un controlador, ya que este fragmento pertenece a la lógica de nuestra aplicación. Lo veremos en la siguiente lección.


Recursos

Enlace de Youtube: https://www.youtube.com/watch?v=PDbOsGlCf7o&list=PLZ2ovOgdI-kWWS9aq8mfUDkJRfYib-SvF&index=3

Enlace sobre la arquitectura de Laravel: https://www.oulub.com/es-ES/Laravel/structure#introduction