Laravel 5, parte 6: Vistas y Helpers

Bueno, ahora que ya tenemos el funcionamiento lógico de nuestra aplicación, sólo nos falta agregar la parte visual. Para ello vamos a tener que crear los archivos para ver, modificar o eliminar las tareas.

Helpers

En mi opinión, siempre prefiero evitar este tipo de herramientas, pero visto y considerando que son muy útiles para la mayoría de los desarrolladores, vamos a crear nuestra aplicación con helpers.

Los helpers nos permiten crear contenido html por medio de código propio del framework, una función a la cual podemos pasar parámetros y ésta se encargará de crear el código html correspondiente.

Así que primero vamos a abrir nuestro archivo «composer.json», y a buscar «require». En mi caso mi archivo es así:

"require": { "php": ">=5.6.4", "laravel/framework": "5.4.*", "laravel/tinker": "~1.0" }

Dentro de la lista, vamos a agregar un ítem más. En mi caso:

"laravelcollective/html": "5.4.*"

Entonces me quedará de este modo:

"require": {
   "php": ">=5.6.4",
   "laravel/framework": "5.4.*",
   "laravel/tinker": "~1.0",
   "laravelcollective/html": "5.4.*"
}

Pero atención, la versión que yo estoy usando de Laravel es la «5.4», si estás usando otra, deberías poner la que corresponde. Podés fijarte en el valor de «laravel/framework», o bien escribir en consola:

php artisan --version

Una vez que terminemos de editar este archivo, vamos a la consola y escribimos lo siguiente:

composer update

Y empezarán a descargarse las dependiencias.

Una vez que termine la descarga desde la consola, editar el archivo «config/app.php», y buscamos dentro de «providers», y dentro de la lista agregamos:

Collective\Html\HtmlServiceProvider::class,

Y en el mismo archivo, dentro de «aliases»:

'Form' => 'Collective\Html\FormFacade',
'Html' => 'Collective\Html\HtmlFacade',

 

Vistas

Bueno, ahora vamos a crear las vistas. Tendremos tres vistas, una para mostrar las tareas, otra para visualizar una en particular y otra para guardarlas (crear o modificar)

Así que dentro de resources/views vamos a crear un directorio llamado tareas, y dentro los tres archivos:

  • index.blade.php
  • show.blade.php
  • save.blade.php

(No te olvides de ‘.blade’ antes de ‘.php’)

Antes de editar el código, vamos a detenernos algo. A la hora de crear interfaces visuales, casi siempre hay código html que se repite entre página y página. Por ejemplo cabeceras, pies de página, archivos externos (css, js, imágenes). Laravel nos permite crear una plantilla base, y luego poder reutilizar dicho diseño, incluyendo solamente en cada una el código que cambia entre página y página.

Si nos fijamos bien dentro de resources/views/layouts/app.blade.php, vamos a ver código html. Aquí podemos modificar si por ejemplo necesitamos agregar un css, un js, o simpemente cambiar el diseño de nuestro sitio.

Por ejemplo, podemos encontrar los enlaces del menú que cambian dependiente de si el usuario está logueado o no:

@if (Auth::guest())

Esta línea indica que el usuario no está logueado, así que va a visualizar en este caso los enlaces para iniciar sesión o bien registrarse.

Vamos a aprovechas para agregar el siguiente enlace para acceder con un link a las tareas, siempre y cuando el usuario esté logueado:

<li>
   <a href="/tareas">
      Tareas
   </a>
</li>

Bueno, a continuación vamos a editar los archivos visuales. Dentro de save.blade.php copiamos el siguiente código:

@extends('layouts.app')
@section('content')
 <div class="container">
    <h1> Guardar tarea </h1>
    {!! Form::open(array('url' => 'tareas/' . $tarea->id, 'method' => $method)) !!}
       <div class="form-group">
          {!! Form::label('titulo', 'Título') !!}
          {!! Form::text('titulo', $tarea->titulo, ['class' => 'form-control']) !!}
       </div>
       <div class="form-group">
          {!! Form::label('descripcion', 'Descripción') !!}
          {!! Form::textarea('descripcion', $tarea->descripcion, ['class'=>'form-control', 'rows' => 2, 'cols' => 40]) !!}
       </div>
       <div class="form-group">
          {!! Form::label('estado', 'Estado') !!}
          <select name="estado_id" id="estado_id" class="form-control"> 
             <option value=""> --- </option>
             @foreach ($estados as $item)
                @if($tarea->id != null && $item->id == $tarea->estado->id)
                   <option selected="selected" value="{{ $item->id }}"> {{ $item->nombre }} </option>
                @else
                   <option value="{{ $item->id }}"> {{ $item->nombre }} </option>
                @endif
             @endforeach
          </select>
       </div>
       {!! Form::submit('Guardar', ['class' => 'btn btn-primary']) !!} 
       {!! link_to('tareas', 'Cancelar', ['class' => 'btn btn-danger']) !!}
    {!! Form::close() !!}
 </div>
@endsection

Bueno, sé que es mucho código, pero vamos a ir viéndolo de a poco.

En primer lugar extendemos de otra vista, la cual tiene una suerte de plantilla para el resto de nuestras interfaces gráficas:

@extends('layouts.app')

Esto dibujará la cabecera y el pie sin necesidad de repetirlo en cada vista.

Comenzando con los helper, primero usamos:

{!! Form::open(array('url' => 'tareas/' . $tarea->id, 'method' => $method)) !!}

Este es un helper para abrir un formulario. La url es ‘tareas’ + barra (/) + id, en caso de que haya un id. Osea este formulario nos va a servir cuando tengamos una tarea nueva o una que vamos a editar. Por eso en la publicación pasado escribimos :

$tarea = new Tarea();

Para una tarea que aún no se ha creado

$tarea = Tarea::find($id);

Con una tarea que ya existe, y que recuperamos por id.

Otra cosa que hay que aclarar es que:

'method' => $method

Será una variable que le pasamos el método. Cuando sea el método create(), le vamos a pasar ‘POST’, que es para crear un nuevo registro; cuando sea el edit(), entonces será ‘PUT’, para modificar.

Y cerramos con:

{!! Form::close() !!}

El resto de los helpers son simplemente elementos de formulario, por ejemplo:

{!! Form::label(‘titulo’, ‘Título’) !!}
{!! Form::text(‘titulo’, $tarea->titulo, [‘class’ => ‘form-control’]) !!}

En el caso de label(), el primer parámetro es el for, y el segundo el texto de la etiqueta.

Mientras que text() es el name, el value por defecto y el tercer parámetro es un array con datos adicionales como la clase que usamos.

Y un select para mostrar los estados:

<select name="estado_id" id="estado_id" class="form-control"> 
   <option value=""> --- </option>
   @foreach ($estados as $item)
      @if($tarea->id != null && $item->id == $tarea->estado->id)
         <option selected="selected" value="{{ $item->id }}"> {{ $item->nombre }} </option>
      @else
         <option value="{{ $item->id }}"> {{ $item->nombre }} </option>
      @endif
   @endforeach
</select>

Verificamos si la tarea ya existe con:

$tarea->id != null

Y luego si coincide con el estado que estamos recorriendo, para ponerla en selected o no:

$item->id == $tarea->estado->id

Finalmente vamos a modificar los métodos create() y edit() que creamos la última vez, permitiendo que se cargue esta vista.

public function create()
{
   $tarea = new Tarea();
   $estados = Estado::all();
   return View('tareas.save')
      ->with('tarea', $tarea)
      ->with('estados', $estados)
      ->with('method', 'POST');
}
public function edit($id)
{
   $tarea = Tarea::where(array(
      'id' => $id,
      'user_id' => Auth::id()
   ))->first();
   $estados = Estado::all();
   return View('tareas.save')
      ->with('tarea', $tarea)
      ->with('estados', $estados)
      ->with('method', 'PUT');
}

Como podemos observar le pasamos por parámetro un dato llamado ‘method’, el cual va a cambiar dependiendo de si lo enviamos por ‘POST’ o  ‘PUT’.

Luego vamos a editar el archivo index.blade.php con el siguiente código:

@extends('layouts.app')
 @section('content')
 <div class="container">
    @if(Session::has('notice'))
       <div class="alert alert-success">
          {{ Session::get('notice') }}
       </div>
    @endif
    <h1> Lista de tareas </h1>
    <div class="row">
       <div class="col-lg-12">
          {!! link_to('tareas/create', 'Crear', ['class' => 'btn btn-primary']) !!}
       </div>
    </div>
    <table class="table">
       <thead>
       <tr>
             <th style="width: 35%"> Título </th>
             <th style="width: 35%"> Estado </th>
             <th style="width: 10%"> </th>
             <th style="width: 10%"> </th>
             <th style="width: 10%"> </th>
          </tr>
       </thead>
       <tbody>
          @foreach ($tareas as $tarea)
             <tr>
                <td> {{ $tarea->titulo }} </td>
                <td> {{ $tarea->estado->nombre }} </td>
                <td>
                   {!! link_to('tareas/'.$tarea->id, 'Ver', ['class' => 'btn btn-primary']) !!}
                </td>
                <td>
                   {!! link_to('tareas/'.$tarea->id.'/edit', 'Editar', ['class' => 'btn btn-primary']) !!}
                </td>
                <td>
                   {!! Form::open(array('url' => 'tareas/' . $tarea->id, 'method' => 'DELETE')) !!}
                      {!! Form::submit('Eliminar', ['class' => 'btn btn-danger']) !!}
                   {!! Form::close() !!}
                </td>
             </tr>
          @endforeach
       </tbody>
    </table>
 </div>
 @endsection

Usamos el helper link_to para crear un enlace al formulario de creación de tareas:

{!! link_to('tareas/create', 'Crear', ['class' => 'btn btn-primary']) !!}

Recorremos las tareas creadas actualmente por el usuario, podremos verlas:

{!! link_to('tareas/'.$tarea->id, 'Ver', ['class' => 'btn btn-primary']) !!}

Editarlas:

{!! link_to('tareas/'.$tarea->id.'/edit', 'Editar', ['class' => 'btn btn-primary']) !!}

O bien, eliminarlas:

{!! Form::open(array('url' => 'tareas/' . $tarea->id, 'method' => 'DELETE')) !!}
   {!! Form::submit('Eliminar', ['class' => 'btn btn-danger']) !!}
{!! Form::close() !!}

Es importante observar que en este último, debemos crear un formulario para hacer un envío con el método ‘DELETE’, al igual que lo hacíamos en el formulario para guardar con ‘POST’ o ‘PUT’.

Y debemos modificar el método index también con el siguiente código:

public function index()
{
   $tareas = User::find(Auth::id())->tareas;
   return View('tareas.index')->with('tareas', $tareas);
}

Por último y para termina vamos a reemplazar show.blade.php con el siguiente código:

@extends('layouts.app')
@section('content')
 <div class="container">
    <h1> {{ $tarea->titulo }} ({{ $tarea->estado->nombre }}) </h1>
    <div class="row">
       <div class="col-lg-12">
          {{ $tarea->descripcion }}
       </div>
       <hr />
       <div class="col-lg-12">
          {!! link_to('tareas', 'Volver', ['class' => 'btn btn-danger']) !!}
       </div>
    </div>
 </div>
@endsection

Solamente para ver la tarea con su descripción.

Y reemplazamos el método por lo siguiente:

public function show($id)
{
   $tarea = Tarea::where(array(
      'id' => $id,
      'user_id' => Auth::id()
   ))->first();
   return View('tareas.show')
      ->with('tarea', $tarea);
}

Anterior: Laravel 5, parte 5: Controladores y Rutas

Siguiente: Laravel 5, parte 7: Validaciones

 

Descargar ejemplo completo

 


4 Respuestas a “Laravel 5, parte 6: Vistas y Helpers”

  1. Hola Fernando, te consulto si los helpers son recomendables, si es preferible evitarlos, o que ventaja tienen respecto a usar codigo html estandar. Gracias!!

    1. Depende. En mi caso en particular los helper de elementos de formulario no los uso, pero los puse en la publicación para las personas que sí lo hacen.

      Yo creo que los que tienen que ver más con manejo de urls son bastante útiles. Por ejemplo para cargar archivos externos como imágenes, css o js; o bien redireccionar a otras partes de la aplicación.

      Saludos!

  2. En el apartado de helpers pones «Así que primero vamos a abrir nuestro archivo “composer.js”,» pero ya me causo confusión no será composer.json, creó la actual versíón de laravel ya incluye laravel collective?

    Muchas gracias por tus tutoriales