Crear tu Primera Aplicaci贸n con Laravel

By Posted on 12603 views

Desde su lanzamiento inicial en 2011, Laravel ha experimentado un crecimiento exponencial. En 2015 se convirti贸 en el m谩s destacado framework PHP en GitHUb.聽

La filosof铆a de Laravel es desarrollar c贸digo PHP聽de forma elegante y simple basado en un modelo MVC(Modelo-Vista-Controlador).聽Cuenta con un c贸digo modular y extensible por medio de un administrador de paquetes y un soporte robusto para el manejo de bases de datos.

Esta gu铆a esta elaborada pensando en personas que est谩n iniciando con Laravel, se desarrollar谩 un sistema de registro para cubrir聽 las operaciones b谩sicas de creaci贸n, lectura, actualizaci贸n y borrado de registros, com煤nmente conocido como CRUD.聽

Requisitos del Servidor

Todos los requerimientos del servidor para el desarrollo de esta gu铆a se encuentran en el art铆culo Instalar Laravel con Apache y MySQL

Crear Base de Datos

Ejecutar en la terminal el siguiente comando:聽

mysql -u root -p

Te pedir谩 la contrase帽a del usuario root, una vez ingreses la contrase帽a correctamente te mostrara el prompt de mysql>

Iniciando MySQL desde la l铆nea de comando
Iniciando MySQL desde la l铆nea de comando

Tambi茅n puedes usar phpmyadmin para crear la base de datos, si lo tienes instalado.聽

Desde la terminal crear la base de datos a utilizar:

CREATE DATABASE laravelcrud;

Crear el usuario y contrase帽a, el cual ser谩 asignado a la base de datos creada:

CREATE USER 'laravel_user'@'127.0.0.1' IDENTIFIED BY 'LaB_101

Asignar a la base de datos el usuario creado:

GRANT ALL ON laravelcrud.* TO 'laravel_user'@'127.0.0.1';

Para recargar la tabla de privilegios, se ejecuta el siguiente comando:

FLUSH PRIVILEGES;

Crear Proyecto Laravel

Ejecutar comando que crear谩 un nuevo proyecto llamado laravelcrud,聽 este comando generar谩 toda la estructura de carpetas,archivos y dependencias necesarias para correr la aplicaci贸n:聽

laravel new laravelcrud
Crear nuevo proyecto Laravel
Crear nuevo proyecto Laravel

Abrir Proyecto en el Editor de Preferencia

Una vez generado el nuevo proyecto Laravel, abrirlo desde el editor de preferencia, personalmente me gusta utilizar Visual Code.聽

Por medio de la terminal acceder a la carpeta del proyecto:

cd laravelcrud

Establecer Configuraci贸n De Base De Datos

Buscar el archivo .env y proceder a poner la configuraci贸n de la base de datos creada y que ser谩 utilizada por la aplicaci贸n:

DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=laravelcrud
DB_USERNAME=laravel_user
DB_PASSWORD=LaB_101$

Para estar seguro que exista conexi贸n entre nuestra aplicaci贸n y la base de datos ejecutar el comando:

php artisan migrate

Este comando crear谩 3 tablas en la base de datos por defecto:聽

  1. migratios
  2. password_resets
  3. users

En la terminal conectado al prompt de MySQL ejecutar :

mysql> use laravelcrud;
mysql> show tables;

Adicional en el proyecto se crearon autom谩ticamente las migraciones para esas tablas en la carpeta generada app–>database->migrations聽

Crear Modelo y Migraci贸n

En la terminal ejecutar :

php artisan make:model Registry -m

Se crear谩n dos archivos:

  1. Registry.php el modelo.
  2. create_registries_table.php la migraci贸n.

Se necesita crear la estructura (schema) de la tabla de registry para ello se modifica el archivo de la migraci贸n reci茅n creado que se encuentra en app–>database–>migrations–>create_registries_table.ph

En la clase creada para la migraci贸n se generan autom谩ticamente dos m茅todos up y down, modificar de la siguiente manera:

<?php

use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;

class CreateRegistriesTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('registries', function (Blueprint $table) {
           
            $table->integer('id')->unsigned();
            $table->string('first_name',50);
            $table->string('second_name',50)->nullable();
            $table->string('surename',50);
            $table->string('second_surename',50)->nullable();
            $table->string('email',100);
            $table->string('cell_phone',50)->nullable();
            $table->string('phone',50)->nullable();
            $table->string('coments',500)->nullable();
            $table->integer('age');
            $table->boolean('flosspainfo')->nullable();
            $table->boolean('fedorainfo')->nullable();
            $table->boolean('latansecinfo')->nullable();

            $table->timestamps();
            $table->primary(array('id', 'email'));

            
        });

        DB::statement('ALTER TABLE registries MODIFY id INTEGER NOT NULL AUTO_INCREMENT');
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('registries');
    }
}

Volver a ejecutar el comando de migraciones :

php artisan migrate

Para validar la creaci贸n de la tabla ejecute comando de base de datos utilizado anteriormente y para validar la creaci贸n de las columnas ejecute desde la terminal con MySQL:

use laravelcrud;
show columns from registries;

Crear Vista Registro

Se genera la primera vista, para ello crear la carpeta registries聽dentro de app–>resources –> views聽聽 y luego聽 聽crear dentro de esta carpeta el archivo create.blade.php:

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>FLOSSPA Asistencia Evento </title>
    <link rel="stylesheet" href="{{asset('css/app.css')}}">
    <link rel="stylesheet" href="{{asset('css/registry.css')}}">
    

  </head>
  <body>
    <div class="container">
    <img alt="FLOSSPA" srcset="{{ URL::to('/images/logo-flosspa.svg') }}">
    
    @if ($errors->any())
      <div class="alert alert-danger">
          <ul>
              @foreach ($errors->all() as $error)
                  <li>{{ $error }}</li>
              @endforeach
          </ul>
      </div><br />
      @endif
      @if (\Session::has('success'))
      <div class="alert alert-success">
          <p>{{ \Session::get('success') }}</p>
      </div><br />
      @endif

    <form method="post" action="{{url('registries')}}" id="formRegistry">
    {{csrf_field()}}
        <div class="row">
          <div class="form-group col-xs-12 col-sm-6 col-md-6">
            <label for="name">Primer Nombre:</label>
            <input type="text" class="form-control" name="first_name"  value={{old('first_name')}}>
          </div>
          <div class="form-group col-xs-12 col-sm-6 col-md-6">
            <label for="name">Segundo Nombre:</label>
            <input type="text" class="form-control" name="second_name" value={{old('second_name')}}>
          </div>
        </div>

         <div class="row">
          <div class="form-group col-xs-12 col-sm-6 col-md-6">
            <label for="name">Primer Apellido:</label>
            <input type="text" class="form-control" name="surename" value={{old('surename')}}>
          </div>
          <div class="form-group col-xs-12 col-sm-6 col-md-6">
            <label for="name">Segundo Apellido:</label>
            <input type="text" class="form-control" name="second_surename" value={{old('second_surename')}}>
          </div>
        </div>

        <div class="row">
          <div class="form-group col-xs-12 col-sm-6 col-md-6">
            <label for="name">Email:</label>
            <input type="text" class="form-control" name="email"  value={{old('email')}}>
          </div>
          <div class="form-group col-xs-12 col-sm-6 col-md-6">
            <label for="name">Edad:</label>
            <input type="text" class="form-control" name="age" value={{old('age')}}>
          </div>
        </div>

        <div class="row">
          <div class="form-group col-xs-12 col-sm-6 col-md-6">
            <label for="name">T茅lefono Residencial:</label>
            <input type="text" class="form-control" name="phone" value={{old('phone')}}> 
          </div>
          <div class="form-group col-xs-12 col-sm-6 col-md-6">
            <label for="name">Celular:</label>
            <input type="text" class="form-control" name="cell_phone" value={{old('cell_phone')}}>
          </div>
        </div>

        <div class="row">
        
          <div class="form-group col-xs-12 col-sm-6 col-md-6">
          <label for="name">Desea recibir informaci贸n de:</label>
          <div class="checkbox">
          
            <label> <input type="checkbox" name="flosspainfo" @if(old('flosspainfo') !== NULL ){{ 'checked' }}@endif> FLOSSPA</label>
          </div>
          <div class="checkbox">
            <label> <input type="checkbox" name="fedorainfo" @if(old('fedorainfo') !== NULL ){{ 'checked' }}@endif> FEDORA</label>
          </div>
          <div class="checkbox disabled">
            <label> <input type="checkbox" name="latansecinfo" @if(old('latansecinfo') !== NULL ){{ 'checked' }}@endif> LATANSEC</label>
          </div>
          </div>
          
        </div>
        
        <div class="row">
          <div class="form-group col-xs-12 col-sm-12 col-md-12">
            <label for="name">Comentarios:</label>
            <textarea class="form-control" rows="5" name="coments" >{{old('coments')}}</textarea>
          </div>
        </div>

        <div class="row">
          
          <div class="form-group col-xs-12 col-sm-12 col-md-12">
            <button type="submit" class="btn btn-success">Agregar Asistencia</button>
          </div>
        </div>
      </form>
    </div>
    <div id="toast-container" class="toast-top-right">
    </div
  </body>
</html>

Para evitar ataques CSRF (del ingl茅s Cross-site request forgery o falsificaci贸n de petici贸n en sitios cruzados) es un tipo de exploit malicioso de un sitio web en el que comandos no autorizados son transmitidos por un usuario en el cual el sitio web conf铆a. Esta vulnerabilidad es conocida tambi茅n por
otros nombres como XSRF, enlace hostil, cabalgamiento de sesi贸n, y ataque autom谩tico. Larvel provee la protecci贸n
{{csrf_field()}}聽.

Para preservar la informaci贸n en el formulario se logra聽 agregando en cada uno de los controles a帽adidos value={{old(‘first_name’)}}聽.

Ahora crear el controlador para desplegar la vista , ejecutar el siguiente comando:

php artisan make:controller RegistryController --resource

Dentro de la carpeta app–>Http–>Controllers se encontrar谩 el controlador, generado autom谩ticamente con todos los m茅todos necesarios para el CRUD.

Para poder tener acceso a los m茅todos creados, se debe agregar una ruta que haga referencia al controlador, para ello se modifica el archivo app–>routes –> web.php

<?php

/*
|--------------------------------------------------------------------------
| Web Routes
|--------------------------------------------------------------------------
|
| Here is where you can register web routes for your application. These
| routes are loaded by the RouteServiceProvider within a group which
| contains the "web" middleware group. Now create something great!
|
*/


Route::resource('registries','RegistryController');

Para ver la lista de rutas que se pueden utilizar, ejecutar:

php artisan route:list

En el m茅todo create del controlador se agrega:聽

public function create()
{  
   return view('registries.create');
}

Iniciar el servidor de desarrollo de Laravel y se podr谩 ver la primera vista:聽

php artisan serve

Cargar en el buscador la URL http://localhost:8000/registries/create

Vista Aplicaci贸n Laravel
Vista Aplicaci贸n Laravel

En la carpeta public–>css聽 se agreg贸 CSS personalizado y adem谩s se creo la carpeta images para agregar la imagen que se muestra en pantalla. El c贸digo lo puedes bajar desde mi cuenta de GitHub.

En el modelo se debe manejar la vulnerabilidad Mass Assignment para ellos se modifica la clase que se encuentra en app–>Registry.php

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Registry extends Model
{
   
    protected $fillable = ['first_name','second_name','surename','second_surename',
                        'email','age','phone','cell_phone','flosspainfo','fedorainfo','latansecinfo','coments']; 
}

Para poder guardar los datos que se env铆en desde la vista se debe modificar el controlador RegistryController.php, incluyendo la clase Registry聽 y la interfaz est谩tica(Facades) Input聽.

use App\Registry;
use Illuminate\Support\Facades\Input;

Ahora se debe modificar el m茅todo store:

public function store(Request $request)
    {
       
        $registry = $this->validate(request(), [
            'first_name' => 'required',
            'surename' => 'required',
            'email' => 'required|email',
            'age' => 'integer|min:0'
          ]);

        
          $flosspainfo = Input::get('flosspainfo') == 'on' ? true :false;
          $fedorainfo = Input::get('fedorainfo') == 'on' ? true :false;
          $latansecinfo = Input::get('latansecinfo') == 'on' ? true :false;
          

          Registry::create([
            'first_name'=> Input::get('first_name'),
            'second_name'=> Input::get('second_name'),
            'surename'=> Input::get('surename'),
            'second_surename'=> Input::get('second_surename'),
            'email'=> Input::get('email'),
            'cell_phone' => Input::get('cell_phone'),
            'phone'=> Input::get('phone'),
            'coments'=> Input::get('coments'),
            'age'=> Input::get('age'),
            'flosspainfo'=> $flosspainfo,
            'fedorainfo'=>  $fedorainfo,
            'latansecinfo'=>  $latansecinfo
          ]);
  
          return back()->with('success', 'Informaci贸n almacenada con 茅xito');
    }

Cargar la vista y tratar de guardar sin llenar los datos, se recibir谩n mensajes de validaci贸n.

Para desplegar los mensajes en espa帽ol se puede utilizar el siguiente el paquete de traducci贸n en espa帽ol.

Vista Listado

Ahora se crear谩 un listado de todos los registros guardados, crear la vista en
app–>resources–>views–> registries–>index.blade.php

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>Index Page</title>
    <link rel="stylesheet" href="{{asset('css/app.css')}}">
  </head>
  <body>
    <div class="container">
    <img src="equilateral.png" alt="FLOSSPA" srcset="{{ URL::to('/images/logo-flosspa.svg') }}">
    <br />
    @if (\Session::has('success'))
      <div class="alert alert-success">
        <p>{{ \Session::get('success') }}</p>
      </div><br />
     @endif
    <table class="table table-striped">
    <thead>
      <tr>
        <th>ID</th>
        <th>Nombre</th>
        <th>Apellido</th>
        <th >Email</th>
        <th >Tel茅fono</th>
        <th >Celular</th>
        <th colspan="2">Acci贸n</th>
      </tr>
    </thead>
    <tbody>
      @foreach($registries as $registry)
      <tr>
        <td>{{$registry['id']}}</td>
        <td>{{$registry['first_name']}}</td>
        <td>{{$registry['surename']}}</td>
        <td>{{$registry['email']}}</td>
        <td>{{$registry['phone']}}</td>
        <td>{{$registry['cell_phone']}}</td>
        <td><a href="{{action('RegistryController@edit', $registry['id'])}}" class="btn btn-warning">Edit</a></td>
        <td>
          <form  onsubmit="return confirm('Do you really want to delete?');" action="{{action('RegistryController@destroy', $registry['id'])}}" method="post">
            {{csrf_field()}}
            <input name="_method" type="hidden" value="DELETE">
            <button class="btn btn-danger" type="submit">Delete</button>
          </form>
        </td>
      </tr>
      @endforeach
    </tbody>
  </table>
  </div>
  </body>
</html

Modificar el controlador agregando la carga de la vista:聽

public function index()
{
    $registries = Registry::all()->toArray();
    return view('registries.index', compact('registries'));
}

Cargar聽 la vista http://localhost:8000/registries

Vista Listado Laravel
Vista del listado de registros

Vista Edici贸n

Crear la funcionalidad de edici贸n de un registro, para ello se inicia creando la vista que es bastante similar a la de la creaci贸n app–>resources–>views–> registries–>edit.blade.php

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>FLOSSPA Editar Asistencia Evento </title>
    <link rel="stylesheet" href="{{asset('css/app.css')}}">
    <link rel="stylesheet" href="{{asset('css/registry.css')}}">
    

  </head>
  <body>
    <div class="container">
    <img src="equilateral.png" alt="FLOSSPA" srcset="{{ URL::to('/images/logo-flosspa.svg') }}">
    
    @if ($errors->any())
      <div class="alert alert-danger">
          <ul>
              @foreach ($errors->all() as $error)
                  <li>{{ $error }}</li>
              @endforeach
          </ul>
      </div><br />
      @endif
      @if (\Session::has('success'))
      <div class="alert alert-success">
          <p>{{ \Session::get('success') }}</p>
      </div><br />
      @endif

    <form method="post" action="{{action('RegistryController@update', $id)}}" id="formRegistry">
    {{csrf_field()}}
    <input name="_method" type="hidden" value="PATCH">
        <div class="row">
          <div class="form-group col-xs-12 col-sm-6 col-md-6">
            <label for="name">Primer Nombre:</label>
            <input type="text" class="form-control" name="first_name"  value="{{$registry->first_name}}" >
          </div>
          <div class="form-group col-xs-12 col-sm-6 col-md-6">
            <label for="name">Segundo Nombre:</label>
            <input type="text" class="form-control" name="second_name" value="{{$registry->second_name}}">
          </div>
        </div>

         <div class="row">
          <div class="form-group col-xs-12 col-sm-6 col-md-6">
            <label for="name">Primer Apellido:</label>
            <input type="text" class="form-control" name="surename" value="{{$registry->surename}}">
          </div>
          <div class="form-group col-xs-12 col-sm-6 col-md-6">
            <label for="name">Segundo Apellido:</label>
            <input type="text" class="form-control" name="second_surename" value="{{$registry->second_surename}}">
          </div>
        </div>

        <div class="row">
          <div class="form-group col-xs-12 col-sm-6 col-md-6">
            <label for="name">Email:</label>
            <input type="text" class="form-control" name="email"  value="{{$registry->email}}">
          </div>
          <div class="form-group col-xs-12 col-sm-6 col-md-6">
            <label for="name">Edad:</label>
            <input type="text" class="form-control" name="age" value="{{$registry->age}}">
          </div>
        </div>

        <div class="row">
          <div class="form-group col-xs-12 col-sm-6 col-md-6">
            <label for="name">T茅lefono Residencial:</label>
            <input type="text" class="form-control" name="phone" value="{{$registry->phone}}"> 
          </div>
          <div class="form-group col-xs-12 col-sm-6 col-md-6">
            <label for="name">Celular:</label>
            <input type="text" class="form-control" name="cell_phone" value="{{$registry->cell_phone}}">
          </div>
        </div>

        <div class="row">
        
          <div class="form-group col-xs-12 col-sm-6 col-md-6">
          <label for="name">Desea recibir informaci贸n de:</label>
          <div class="checkbox">
          
            <label> <input type="checkbox" name="flosspainfo" @if($registry->flosspainfo == true ){{ 'checked' }}@endif> FLOSSPA</label>
          </div>
          <div class="checkbox">
            <label> <input type="checkbox" name="fedorainfo" @if($registry->fedorainfo == true){{ 'checked' }}@endif> FEDORA</label>
          </div>
          <div class="checkbox disabled">
            <label> <input type="checkbox" name="latansecinfo" @if($registry->latansecinfo == true ){{ 'checked' }}@endif> LATANSEC</label>
          </div>
          </div>
          
        </div>
        
        <div class="row">
          <div class="form-group col-xs-12 col-sm-12 col-md-12">
            <label for="name">Comentarios:</label>
            <textarea class="form-control" rows="5" name="coments" >{{$registry->coments}}</textarea>
          </div>
        </div>

        <div class="row">
          
          <div class="form-group col-xs-12 col-sm-12 col-md-12">
            <button type="submit" class="btn btn-success">Update</button>
          </div>
        </div>
      </form>
    </div>
    <div id="toast-container" class="toast-top-right">
    </div
  </body>
</html>

Modificar el m茅todo edit, as铆 como el m茅todo update del controlador :

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

    /**
     * Update the specified resource in storage.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  int  $id
     * @return \Illuminate\Http\Response
     */
    public function update(Request $request, $id)
    {
      
       $registry = Registry::find($id);
        $this->validate(request(), [
            'first_name' => 'required',
            'surename' => 'required',
            'email' => 'required|email',
            'age' => 'integer|min:0'
          ]);

        
          $registry->first_name = Input::get('first_name');
          $registry->second_name =  Input::get('second_name');
          $registry->surename = Input::get('surename');
          $registry->second_surename =  Input::get('second_surename');
          $registry->email = Input::get('email');
          $registry->cell_phone =  Input::get('cell_phone');
          $registry->phone = Input::get('phone');
          $registry->coments = Input::get('coments');
          $registry->age = Input::get('age');
          $registry->flosspainfo = Input::get('flosspainfo') == 'on' ? true :false;
          $registry->fedorainfo = Input::get('fedorainfo') == 'on' ? true :false;
          $registry->latansecinfo = Input::get('latansecinfo') == 'on' ? true :false;
          $registry->save();
          
  
          return back()->with('success', 'Registry updated successfully');
          
    }

Borrado De Registro

Para borrar un registro agregar en el m茅todo destroy del controlador lo siguiente:

public function destroy($id)
{
  $registry = Registry::find($id);
  $registry->delete();
  return redirect('registries')->with('success','Registry has been  deleted');
}

Puedes encontrar el proyecto completamente funcional en mi cuenta de GitHub.

驴Qu茅 piensas del art铆culo?

Tu direcci贸n de correo electr贸nico no ser谩 publicada. Los campos obligatorios est谩n marcados con *

3 × 1 =

9 Comments
  • Alexis Figueroa
    septiembre 18, 2019

    excelente tutorial me ha servido mucho… un millon de gracias…

    • Davis Alvarez
      noviembre 12, 2019

      Con mucho gusto.

      • Darwing Salgado
        mayo 16, 2023

        Gracias David ,ha Ciro muy util para mi estoy iniciando en esto de la programaci贸n y la verdad me encanta mucho ,quisiera hacer una aplicaci贸n funcional para registrar datos y manipulaci贸n de datos en un peque帽o negocio .pero no tengo mucha idea creo con el tiempo aprender茅 m谩s .

  • Gabriel Gamboa
    noviembre 3, 2019

    Wow Davis, genial, no sab铆a conoc铆a este nivel de expertise en Laravel de tu parte, estoy iniciando y encuentro este interesante y completo art铆culo amigo,
    Simplemente, genial,
    Muchas Gracias por tu tiempo

    • Davis Alvarez
      noviembre 12, 2019

      脡xitos en tu proceso de aprendizaje de esta herramienta.

  • Julio ayala
    noviembre 9, 2019

    Muy bueno
    Mo pruebo y comento el resultado

    • Davis Alvarez
      noviembre 12, 2019

      Me alegra que te sirva.

  • David Parra
    julio 4, 2021

    De pana me sirvi贸 de mucho agradecido

  • Juan Carlos
    octubre 3, 2022

    Hola, tengo problemas al trabajar su c贸digo.
    Me aparece el siguiente c贸digo. Target class [RegistryController] does not exist. Mi error me aparece en Laravel 9.
    Ayuda, por favor.