Laravel 6 - CRUDamente simple!

admin
php
laravel
tutorial
crud

En esta ocasion crearemos una simple aplicacion CRUD.

Como es normal, empezaremos con definiciones:

CRUD
Create, Read, Update, Delete. Son las operaciones basicas en una aplicacion web con base de datos donde permite crear un registro, leer el registro, actualizar los datos del registro y finalmente eliminar un registro.

Muy bien, con eso fuera del camino, aqui van los pasos que vamos a seguir:

  • Instalar Laravel
  • Configurar las credenciales para la base de datos
  • Generar un Modelo y Migracion
  • Crear un Controlador y Ruta
  • Iniciar servidor de prueba
  • Crear las Vistas

Instalar Laravel

Muy bien, para instalar Laravel primeramente debemos tener instalado Composer. Una vez resuelto esto, instalamos Laravel con el siguiente comando:

composer create-project --prefer-dist laravel/laravel crudapp

Esto creara una carpeta llamada crudapp donde se instalar√° Laravel y toda la estructura del proyecto. Fin del paso 1.

Configurar las credenciales para la base de datos

Abrir el archivo .env que se encuentra en la raiz del directorio del proyecto, ubicar la seccion de la base de datos y modificar los valores que les muestro a continuacion:

DB_CONNECTION=mysql 
DB_HOST=127.0.0.1 
DB_PORT=3306 
DB_DATABASE=nombre_base_de_datos
DB_USERNAME=usuario_base_de_datos
DB_PASSWORD=clave_base_de_datos

Previamente debe existir la base de datos mencionada. De no existir, hacerlo en este momento. Clic aqui si no sabes como hacerlo. Fin del paso 2.

Generar un Modelo y Migracion

En el post anterior habiamos hablado muy por encima lo que es el Modelo, el esquema de como es la estructura de una entidad o tabla en la base de datos, aqui tambien podremos ver sus relaciones con otros Modelos (mas de esto en otro proyecto). Iniciemos creando el Modelo:

php artisan make:model Book -m

Este comando creara un archivo llamado Book.php en el directorio app/, este es nuestro Modelo. La opcion -m crea el archivo migracion, el cual podemos encontrar en database/migrations/, con el nombre <timestamp>-create_books_table.php. Vamos a editar estos archivos.

Primeramente modifiquemos el archivo de migracion de la siguiente manera:

<?php 
  
use Illuminate\Support\Facades\Schema; 
use Illuminate\Database\Schema\Blueprint; 
use Illuminate\Database\Migrations\Migration; 
   
class CreateBooksTable extends Migration 
{ 
    /** 
     * Run the migrations. 
     * 
     * @return void 
     */ 
    public function up() 
    { 
        Schema::create('books', function (Blueprint $table) { 
            $table->increments('id'); 
            $table->string('titulo'); 
            $table->string('autor'); 
            $table->text('resumen'); 
            $table->timestamps(); 
        }); 
    } 
   
    /** 
     * Reverse the migrations. 
     * 
     * @return void 
     */ 
    public function down() 
    { 
        Schema::dropIfExists('books'); 
    } 
}

Una vez realizado esto, crearemos la tabla books en la base de datos con las columnas titulo, autor, resumen. Las columnas id, timestamps son parte del control de cambios de la tabla, ya hablaremos de eso mas adelante. Para crear la tabla en la base de datos, ejecutamos el siguiente comando:

php artisan migrate

Ahora vamos al archivo del Modelo y lo editamos asi:

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Book extends Model
{
    protected $fillable = [
     'titulo',
     'autor',
     'resumen',
    ];
}

Con esto le decimos al modelo que los campos titulo, autor, resumen seran llenados por el usuario de la aplicacion.

Crear un Controlador y Ruta

El controlador maneja la logica de nuestra aplicacion, es quien se encarga de obtener los datos del Modelo y pasarselos a la Vista para presentarselo al usuario y a su vez de obtener los datos del usuario para pasarlos al Modelo para ser guardados en la base de datos. Para crear el controlador ejecutamos:

php artisan make:controller BookController --resource

Este comando creara un archivo en app/Http/Controllers llamado BookController.php. Si abrimos este archivo podemos ver que tiene muchos metodos ya escritos para nosotros. Cada uno de estos metodos seran llamados para cada accion que realicemos con nuestra aplicacion, estos metodos son: index, store, create, update, destroy, show, edit.

Pero para acceder a estos metodos, debemos crear las rutas, la direccion web que invoca estos metodos. Para esto vamos a routes/ y abrimos el archivo web.php y le agregamos la siguiente linea:

<?php 

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

En el controlador, BookController agregar la siguiente linea al metodo create:

// En la parte superior debemos tener las siguientes importaciones:
// use App\Book;
// use Illuminate\Http\Request;

public function create()
{
    return 'Create a Book object!';
}

Iniciar servidor de prueba

Para probar que todo va bien, Laravel viene con un servidor de prueba, el cual podemos ejecutar con el siguiente comando:

php artisan serve

Esto ejecuta un servidor web en el puerto 8000, al cual vamos a acceder con la siguiente direccion: http://localhost:8000/books/create

Si ven la siguiente imagen:

Screenshot 1

Perfecto, hasta ahora todo bien! Ahora debemos editar el controlador de la siguiente manera:

<?php

namespace App\Http\Controllers;

use App\Book;
use Illuminate\Http\Request;

class BookController extends Controller
{
    /**
     * Display a listing of the resource.
     *
     * @return \Illuminate\Http\Response
     */
    public function index()
    {
        $books = Book::all();
        return view('books.index', compact('books'));
    }

    /**
     * Show the form for creating a new resource.
     *
     * @return \Illuminate\Http\Response
     */
    public function create()
    {
        //
        return view('books.create');
    }

    /**
     * Store a newly created resource in storage.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return \Illuminate\Http\Response
     */
    public function store(Request $request)
    {
        $request->validate([
            'titulo'=>'required',
            'autor'=>'required',
            'resumen'=>'required'
        ]);

        $book = new Book([
            'titulo' => $request->get('titulo'),
            'autor' => $request->get('autor'),
            'resumen' => $request->get('resumen'),
        ]);
        $book->save();
        return redirect('/books')->with('success', 'Book saved!');
    }

    /**
     * Display the specified resource.
     *
     * @param  int  $id
     * @return \Illuminate\Http\Response
     */
    public function show($id)
    {
        // Por ahora este metodo no lo usaremos
    }

    /**
     * Show the form for editing the specified resource.
     *
     * @param  int  $id
     * @return \Illuminate\Http\Response
     */
    public function edit($id)
    {
        $book = Book::find($id);
        return view('books.edit', compact('book'));
    }

    /**
     * Update the specified resource in storage.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  int  $id
     * @return \Illuminate\Http\Response
     */
    public function update(Request $request, $id)
    {
        $request->validate([
            'titulo'=>'required',
            'autor'=>'required',
            'resumen'=>'required'
        ]);

        $book = Book::find($id);
        $book->titulo = $request->get('titulo');
        $book->autor = $request->get('autor');
        $book->resumen = $request->get('resumen');
        $book->save();

        return redirect('/books')->with('success', 'Book updated!');
    }

    /**
     * Remove the specified resource from storage.
     *
     * @param  int  $id
     * @return \Illuminate\Http\Response
     */
    public function destroy($id)
    {
        $book = Book::find($id);
        $book->delete();

        return redirect('/books')->with('success', 'Book deleted!');
    }
}

Y con esto ya estamos listos para el siguiente y ultimo paso…

Crear las Vistas

Cuando se probo que las rutas y metodos esten funcionando correctamente, lo unico que hicimos fue devolver texto. Obviamente no es lo que esperamos que suceda cuando queremos crear un objeto dentro de nuestra aplicacion, queremos ingresar datos para que sean almacenados en la base de datos! Es por eso que en el paso anterior hemos cambiado ese comportamiento y vemos que ahora ciertos metodos, index, show, create, edit, devuelven algo llamado view, una vista, una pagina web para que el usuario interactue con nuestra aplicacion. Para esto, abramos el directorio resources/views/, creamos una carpeta llamado books y dentro de esta carpeta crearemos los siguientes archivos:

  • layout.blade.php
  • index.blade.php
  • create.blade.php
  • edit.blade.php

Los cuales editaremos de la siguiente manera:

layout.blade.php

<!DOCTYPE html>
<html>
<head>
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Laravel 6 + MySQL CRUD Tutorial</title>
    <meta name="csrf-token" content="{{ csrf_token() }}">
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css">
</head>
<body>
    <div class="container">
        @yield('content')
    </div>
    <script src="{{ asset('js/app.js') }}" type="text/js"></script>
</body>
</html>

index.blade.php

@extends('books.layout')
   
@section('content')
<div class="row">
<h2>Listado de Libros</h2>
</div>

<div class="row">
    <div class="col-md-10 offset-md-1">
        <a href="{{ route('books.create') }}" class="btn btn-primary mb-2">Crear</a>
        <table class="table table-striped">
            <thead>
                <tr>
                    <th>Titulo</th>
                    <th>Autor</th>
                    <th>Acciones</th>
                </tr>
            </thead>
            <tbody>
            @foreach($books as $book)
                <tr>
                    <td>{{ $book->titulo }}</td>
                    <td>{{ $book->autor }}</td>
                    <td>
                        <a href="{{ route('books.edit',$book->id)}}" class="btn btn-secondary">Editar</a>
                        <form action="{{ route('books.destroy', $book->id)}}" method="post">
                            {{ csrf_field() }}
                            @method('DELETE')
                            <button class="btn btn-danger" type="submit">Eliminar</button>
                        </form>
                    </td>
                </tr>
            @endforeach
            </tbody>
        </table>
    </div>
</div>
@endsection

create.blade.php

@extends('books.layout')
   
@section('content')
<div class="row">
<h2>Creacion de Libro</h2>
</div>

<div class="row">
    <div class="col-md-8 offset-md-2">
        <form action="{{ route('books.store') }}" method="POST" name="nuevo_libro">
            {{ csrf_field() }}
            <div class="form-row">
                <label for="book_titulo">Titulo</label>
                <input type="text" name="titulo" id="book_titulo" class="form-control" placeholder="Titulo del Libro">
                <span class="text-danger">{{ $errors->first('titulo') }}</span>
            </div>
            <div class="form-row">
                <label for="book_autor">Autor</label>
                <input type="text" name="autor" id="book_autor" class="form-control" placeholder="Autor del Libro">
                <span class="text-danger">{{ $errors->first('autor') }}</span>
            </div>
            <div class="form-row">
                <label for="book_resumen">Resumen</label>
                <textarea name="resumen" id="book_resumen" class="form-control" placeholder="Resumen del Libro"></textarea>
                <span class="text-danger">{{ $errors->first('resumen') }}</span>
            </div>
            <button type="submit" class="btn btn-primary">Guardar</button>
        </form>
    </div>
</div>
@endsection

edit.blade.php

@extends('books.layout')
   
@section('content')
<div class="row">
<h2>Actualizacion de Libro</h2>
</div>

<form action="{{ route('books.update', $book->id) }}" method="POST" name="actualizar_libro">
    {{ csrf_field() }}
    @method('PATCH')
    <div class="form-group">
        <label for="book_titulo">Titulo</label>
        <input type="text" name="titulo" id="book_titulo" class="form-control" value="{{ $book->titulo }}">
        <span class="text-danger">{{ $errors->first('titulo') }}</span>
    </div>
    <div class="form-group">
        <label for="book_autor">Autor</label>
        <input type="text" name="autor" id="book_autor" class="form-control" value="{{ $book->autor }}">
        <span class="text-danger">{{ $errors->first('autor') }}</span>
    </div>
    <div class="form-group">
        <label for="book_resumen">Resumen</label>
        <textarea name="resumen" id="book_resumen" class="form-control">
            {{ $book->resumen }}
        </textarea>
        <span class="text-danger">{{ $errors->first('resumen') }}</span>
    </div>
    <button type="submit" class="btn btn-primary">Guardar</button>
</form>
@endsection

Con esto, hemos terminado nuestra aplicacion. Dejenme explicar un par de componentes de las vistas.

Blade
Blade es un motor de plantillas que permite el reuso de componentes para crear increibles presentaciones. De esta manera, podemos generar una plantilla base (layout) y que esta sea usada por las vistas que son mostradas al usuario (index, create, edit), de esta manera toda la aplicacion tiene un diseño consistente.
@extends()
Esta es la directiva de Blade que define que este archivo es hijo de un archivo mayor (layout, en este caso), esto es el contenido de este archivo inyectarlo en el padre para la visualizacion.
@section(<nombre>)
Una plantilla padre puede tener varias secciones que pueden ser llenados por el hijo, cada una de estas secciones deben tener un nombre unico. De esta manera, en las vistas hijo solo se escribe el contenido a ser llenado en el padre, evitando repetir codigo.

Ahora, si no tienen todavia ejecutando el servidor, ejecutenlo con el comando:

php artisan serve

Y vayan a la direccion http://localhost:8000/books y deberian ver algo asi:

Screenshot 2

Al presionar el boton de Crear, deberian ver lo siguiente:

Screenshot 3

Una vez ingresado los datos del libro, deberian regresar a la pagina de listado y ver el libro que han ingresado, como el siguiente ejemplo:

Screenshot 4

El presionar Editar, podremos editar los datos ingresados:

Screenshot 5

Y finalmente, al presionar Eliminar, el libro se elimina.

Con esto podemos dar por finalizado por ahora el tutorial de una aplicacion CRUD simple. Aunque queda un metodo pendiente show. Esto se los dejo de tarea, investiguen, lean, implementen. Si tienen algun error o problema, me lo dejan en la caja de comentarios abajo que los respondere lo mas pronto posible.

Hasta la proxima.