Laravel: Listar y leer registros (parte 13)

Laravel: Listar y leer registros (parte 13)

Archivos:

  • app/Http/controllers/CursoController.php
  • resources/views/cursos/index.blade.php
  • resources/views/layouts/plantilla.blade.php
  • routes/web.php
  • resources/views/cursos/show.blade.php

Listar registros

Según hemos aprendido en lecciones anteriores, podemos mostrar la colección completa de cursos si añadimos estas líneas al método index de CursoController:

$cursos = Curso::all();
return $cursos;

Para poder darle formato a estos registros, tenemos que pasarle la colección a la vista. Por lo tanto, eliminamos la segunda línea (return $cursos) y se la pasamos a la vista de la siguiente manera:

$cursos = Curso::all();
return view("cursos.index", compact('cursos'));

Ahora podemos utilizar la variable cursos en la vista. Abrimos index.blade.php, y usamos este bucle foreach escrito en «formato blade», en el que imprimiremos una lista ul de los cursos:

@section('content')
    <h1>Bienvenido a la página de cursos</h1>
    <ul>
        @foreach ($cursos as $curso)
            <li>{{$curso}}</li>
        @endforeach
    </ul>
@endsection

Listar parte de los registros

Vamos a mostrar sólo el nombre de cada curso, para ello en vez de {{$curso}} accedemos a la propiedad name.

@section('content')
    <h1>Bienvenido a la página de cursos</h1>
    <ul>
        @foreach ($cursos as $curso)
            <li>{{$curso->name}}</li>
        @endforeach
    </ul>
@endsection

Así podríamos acceder a cualquier propiedad de los cursos (id, descripción…).

Paginar registros

Hagamos el código más eficiente mostrando los resultados paginados. Para ello recuperaremos los cursos en el controlador con otro método distinto a all():

$cursos = Curso::paginate();
return view("cursos.index", compact('cursos'));

Esto mostrará sólo la primera página, y debería acceder a la url http://localhost/blog/public/cursos?page=2 para la siguiente.

Agregaremos unos controles para poder navegar entre las páginas. Añadimos lo siguiente al final de la vista:

    <ul>
        @foreach ($cursos as $curso)
            <li>{{$curso->name}}</li>
        @endforeach
    </ul>
    {{$cursos->links()}}

Primer uso de Tailwind

Tanto los botones de Previus y Next como los número de página tienen estilos prestablecidos que utilizan las clases de tailwind. Instalemos la librería tailwind para ver los estilos: accediento a tailwindcss.com podemos copiar este cdn y pegarlo en la plantilla que estamos usando, que anteriormente hemos llamado plantilla.blade.php:

<!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 -->
    <script src="https://cdn.tailwindcss.com"></script>
</head>

(...)

Con la simple adición de este fragmento de código en la plantilla, todas nuestras vistas se beneficiarán del css de tailwind, y veremos un resultado de la paginación más agradable. De momento no usamos tailwind, así que comentamos la línea.

Ajuste en las rutas

Vamos a realizar un pequeño ajuste en las rutas de nuestro proyecto.

Para comenzar, en el archivo routes/web.php, le daremos la propiedad name a la ruta. Concretamente, a la ruta «cursos/create» le daremos el nombre de «cursos.create». A las otras rutas les daremos su parámetro también, para usarlas más adelante. Esto permite cambiar la ruta con mucha facilidad. Podemos hacerlo con la ruta agrupada o con la ruta normal, a continuación pongo el código necesario para hacerlo en ambos casos:

// ruta agrupada

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

// ruta normal

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

Al comienzo de la vista index.blade.php, donde estábamos haciendo la paginación, podemos hacer referencia a esta ruta de la siguiente manera:

@section('content')
    <h1>Bienvenido a la página de cursos</h1>    
     {{-- <a href="cursos/create">Crear curso</a> --}}
    <a href="{{route('cursos.create')}}">Crear curso</a>

Si quisiéramos, podríamos cambiar el nombre de la ruta sin preocuparnos de que el enlace siga apuntando a la misma ruta:

// podríamos tener la ruta que queramos, todo seguirá funcionando:
(...)
    Route::get('blablabla','create')->name('cursos.create');
(...)

Una página para cada curso

Usaremos una ruta que ya teníamos para que cada elemento de la lista sea un enlace a cada página del curso. Para ello, convertiremos cada elemento de la lista en un enlace a una de nuestras rutas, a al que hemos añladido el atributo name (como hemos hecho en este mismo artículo, más arriba):

(...)
    Route::get('cursos/{curso}','show')->name('cursos.show');
(...)

Dentro de la vista:

<li>
<a href="{{route('cursos.show')}}">{{$curso->name}}</a> 
</li>

Pero esto nos devolverá un error, porque show necesita un parámetro. Así, tenemos que pasarle algo del registro, como puede ser el id. Veamos cómo se mostraría así:

<li>
{{route('cursos.show',$curso->id)}} 
</li>

Esas son las rutas que queremos. Dejemos el código así:

 @foreach ($cursos as $curso)

      {{-- <li>{{$curso->name}}</li> --}}
      {{-- <li>{{route('cursos.show')}}</li>  --}}
      {{-- <li>{{route('cursos.show', $curso->id)}}</li>  --}}

      <li>
      <a href="{{route('cursos.show', $curso->id)}}">{{$curso->name}}</a> 
       </li>

@endforeach

Afinando el código

Haremos una serie de cambios en nuestro código para mejorarlo:

Cambiamos la función show de nuestro controlador. Estaba de la siguiente manera:

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

Ahora le pasaremos la id como variable, y dentro recuperaremos el curso con esa id:

     public function show($id){
        $curso = Curso::find($id);
        return view("cursos.show", compact("curso"));
    }

Si visitamos alguno de los enlaces de la lista, ahora se mostrará el curso completo, pero con un mal formato. Vamos a la vista cursos.blade.php y mostraremos el nombre, el nombre en el título y la categoría, además de un enlace para volver a la lista de cursos:

@extends('layouts.plantilla')

@section('title', $curso->name)

@section('content')
    {{-- <h1>Url con la variable <?php echo $curso?></h1> --}}
    <h1>Bienvenido al curso {{$curso->name}}</h1>
    <a href="{{route('cursos.index')}}">Volver a cursos</a>
    <p><strong>Categoría: </strong>{{$curso->categoria}}</p>
    <p><strong>Descripción: </strong>{{$curso->description}}</p>
@endsection

Recursos:

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