Como crear un CRUD con Galería de Imágenes en Laravel 6.2 y Bootstrap 4 – Parte 1

Demo

En las aplicaciones actuales las imágenes son parte importante de un Proyecto Web, estas muestran al usuario ciertas vistas de un producto o un elemento en particular logrando generar en el usuario una mejor experiencia y Navegación que puede terminar en la compra de un producto por parte del usuario visitante, este es el objetivo de muchas tiendas online, en este Tutorial vamos aprender a insertar un registro en la Base de Datos con múltiples imágenes.

Partes

Antes de continuar con este Tutorial te recomiendo leer los siguientes artículos:

Leyendo los artículos anteriores estarás mas Familiarizado con este Tutorial, si ya conoces sobre Laravel entonces puedes continuar con este Tutorial, no hay problema.

Antes de continuar con el Proyecto recuerda que en la Documentación de Laravel 6.2 nos pide que nuestro servidor cuente con las siguientes características:

  • PHP >= 7.2.0
  • BCMath PHP Extension
  • Ctype PHP Extension
  • JSON PHP Extension
  • Mbstring PHP Extension
  • OpenSSL PHP Extension
  • PDO PHP Extension
  • Tokenizer PHP Extension
  • XML PHP Extension

Si tu servidor tiene las características mencionadas en la lista, no tendrás problemas para trabajar con Laravel 6.2

Nuevo Proyecto

Vamos a crear un nuevo Proyecto en Laravel, me ubico en un directorio en donde quiero crear mi proyecto, luego abro mi consola de comandos y ejecuto el siguiente comando para crear un nuevo proyecto en Laravel 6.2

laravel new miproyecto 

...
... (Continua la Creación del Nuevo Proyecto)
...

Con esto se me ha creado la siguiente estructura de directorios y archivos que componen core del Framework Laravel 6.2 con el cual crearé mi Proyecto

/miproyecto
├── /app 
├── /bootstrap
├── /config
├── /database 
├── /node_modules  
├── /public
├── /resources
├── /routes
├── /storage
├── /tests
├── /vendor
├──  .editorconfig
├──  .env
├──  .env.example
├──  .styleci.yml
├──  artisan
├──  composer.json
├──  composer.lock
├──  package.json
├──  phpunit.xml
├──  server.php
├──  webpack.mix.js

Para verificar que mi proyecto se ha creado correctamente, corro el servidor de Laravel e ingreso a la ruta local http://localhost:8000/ en mi navegador

php artisan serve 

Laravel development server started: http://127.0.0.1:8000
[Thu Dec  5 10:23:25 2019] 127.0.0.1:18149 [200]: /favicon.ico

Y compruebo que el proyecto se ha creado correctamente

Nota: Personalmente antes de pasar mi proyecto a producción o subirlo a un servidor, primero lo trabajo en mi servidor local utilizando XAMPP o Laragon.

Bootstrap 4

Para crear mis vistas voy a usar Bootstrap 4, este lo podemos usar mediante el Scaffolding JavaScript y CSS que Laravel nos brinda, este Scaffolding no solamente nos permite trabajar con Bootstrap si no también nos permite trabajar con React y Vue y probablemente agreguen nuevas herramientas en futuras versiones de Laravel.

Para trabajar con el Scaffolding Javascript y CSS debo de instalarlo ejecutando el siguiente comando

composer require laravel/ui --dev 
...
... (Continua la instalación)
...

Ahora tengo soporte para instalar Bootstrap, React o Vue y como yo usaré Bootstrap entonces lo instalo ejecutando el siguiente comando

php artisan ui bootstrap 
... 
... (Continua la instalación) 
...

Por ultimo ejecuto el siguiente comando para compilar Bootstrap en mi Proyecto

npm install && npm run dev
...
... (Continua la instalación) 
...

Con esto ya tengo instalado Bootstrap 4 que incluye jQuery y demás librerías necesarias para que Bootstrap funcione correctamente.

Base de Datos

Voy a utilizar el motor de Base de Datos MySQL, entonces creo una base de datos llamada productos y dentro de esta base de datos voy a crear una tabla llamada bicicletas en donde guardare los registros, cada uno con su galería de imágenes.

Mi base de datos productos la he creado manualmente utilizando la interface de PHPMyAdmin y ahora debo indicarle a Laravel 6.2 la Base de Datos que voy a utilizar para mi Proyecto, para esto abro el archivo .env este archivo se encuentra en miproyecto > .env

/miproyecto
├── /app 
├── /bootstrap
├── /config
├── /database 
├── /node_modules  
├── /public
├── /resources
├── /routes
├── /storage
├── /tests
├── /vendor
├──  .editorconfig
├──  .env // Abro este Archivo 
├──  .env.example
├──  .styleci.yml
├──  artisan
├──  composer.json
├──  composer.lock
├──  package.json
├──  phpunit.xml
├──  server.php
├──  webpack.mix.js

Y dentro del archivo .env y escribo el nombre de mi Base de Datos productos dentro de la variable DB_DATABASE

APP_NAME=Laravel
APP_ENV=local
APP_KEY=base64:teSknBZgkAV9FkIIWOpToK9jnCX72BsEaxJJpWHxtuE=
APP_DEBUG=true
APP_URL=http://localhost

LOG_CHANNEL=stack

DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=productos // Aquí coloco el nombre de mi Base de Datos 'productos' 
DB_USERNAME=root
DB_PASSWORD=

BROADCAST_DRIVER=log
CACHE_DRIVER=file
QUEUE_CONNECTION=sync
SESSION_DRIVER=file
SESSION_LIFETIME=120

REDIS_HOST=127.0.0.1
REDIS_PASSWORD=null
REDIS_PORT=6379

MAIL_DRIVER=smtp
MAIL_HOST=smtp.mailtrap.io
MAIL_PORT=2525
MAIL_USERNAME=null
MAIL_PASSWORD=null
MAIL_ENCRYPTION=null

AWS_ACCESS_KEY_ID=
AWS_SECRET_ACCESS_KEY=
AWS_DEFAULT_REGION=us-east-1
AWS_BUCKET=

PUSHER_APP_ID=
PUSHER_APP_KEY=
PUSHER_APP_SECRET=
PUSHER_APP_CLUSTER=mt1

MIX_PUSHER_APP_KEY="${PUSHER_APP_KEY}"
MIX_PUSHER_APP_CLUSTER="${PUSHER_APP_CLUSTER}"

Migraciones y Tablas en la Base de Datos

Ahora voy a crear 2 tablas, una la llamaré bicicletas y la otra la llamaré img_bicicletas

Tabla bicicletas

Creo la migración para la tabla bicicletas ejecutando el siguiente comando:

php artisan make:migration create_bicicletas_table

Created Migration: 2019_12_05_154536_create_bicicletas_table

Se me ha creado un archivo PHP para crear la tabla bicicletas, este archivo se encuentra en database > migrations > 2019_12_05_153841_create_bicicletas_table.php

/miproyecto
├── /app 
├── /bootstrap
├── /config
├── /database
    ├── /factories    
    ├── /migrations
        ├── 2014_10_12_000000_create_users_table.php 
        ├── 2014_10_12_100000_create_password_resets_table.php 
        ├── 2019_08_19_000000_create_failed_jobs_table.php 
        ├── 2019_12_05_153841_create_bicicletas_table.php // Abro este Archivo 
    ├── /seeds  
├── /node_modules  
├── /public
├── /resources
├── /routes
├── /storage
├── /tests
├── /vendor
├──  .editorconfig
├──  .env
├──  .env.example
├──  .styleci.yml
├──  artisan
├──  composer.json
├──  composer.lock
├──  package.json
├──  phpunit.xml
├──  server.php
├──  webpack.mix.js

Abro el archivo 2019_12_05_153841_create_bicicletas_table.php y en la función up() agrego los campos para mi tabla bicicletas, mi tabla tendrá los campos id, nombre, precio, stock, imagenes, url y al final mediante $table->timestamps() y $table->softDeletes() agrego los campos created_at, updated_at y deleted_at

/**
 * Run the migrations.
 *
 * @return void
 */
public function up()
{
    Schema::create('bicicletas', function (Blueprint $table) {
        $table->bigIncrements('id');
        $table->string('nombre');
        $table->string('precio');
        $table->string('stock');
        $table->integer('imagenes')->unsigned();
        $table->string('url');
        $table->timestamps();
        $table->softDeletes();
    });
}

A continuación todo el código completo del archivo 2019_12_05_153841_create_bicicletas_table.php

<?php

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

class CreateBicicletasTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('bicicletas', function (Blueprint $table) {
            $table->bigIncrements('id');
            $table->string('nombre');
            $table->string('precio');
            $table->string('stock');
            $table->integer('imagenes')->unsigned();
            $table->string('url');
            $table->timestamps();
            $table->softDeletes();
        });
    }

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

Ahora ejecuto el siguiente comando para ejecutar la migración y crear la tabla bicicletas en la base de datos

php artisan migrate 

Migrating: 2019_12_05_153841_create_bicicletas_table
Migrated:  2019_12_05_153841_create_bicicletas_table (0.19 seconds)

Con esto he creado la tabla bicicletas, en esta tabla insertaré los registros y cada registro tendrá múltiples imágenes o su propia galería de imágenes

Tabla img_bicicletas

Esta tabla va servir para almacenar las imágenes que correspondan a una bicicleta o registro de la tabla bicicletas, creo la migración para la tabla img_bicicletas ejecutando el siguiente comando:

php artisan make:migration create_img_bicicletas_table

Created Migration: 2020_01_20_170852_create_img_bicicletas_table

Se me ha creado un archivo PHP para crear la tabla img_bicicletas, este archivo se encuentra en database > migrations > 2020_01_20_170852_create_img_bicicletas_table.php

/miproyecto
├── /app 
├── /bootstrap
├── /config
├── /database
    ├── /factories    
    ├── /migrations
        ├── 2014_10_12_000000_create_users_table.php 
        ├── 2014_10_12_100000_create_password_resets_table.php 
        ├── 2019_08_19_000000_create_failed_jobs_table.php 
        ├── 2019_12_05_153841_create_bicicletas_table.php 
        ├── 2020_01_20_170852_create_img_bicicletas_table.php // Abro este Archivo 
    ├── /seeds  
├── /node_modules  
├── /public
├── /resources
├── /routes
├── /storage
├── /tests
├── /vendor
├──  .editorconfig
├──  .env
├──  .env.example
├──  .styleci.yml
├──  artisan
├──  composer.json
├──  composer.lock
├──  package.json
├──  phpunit.xml
├──  server.php
├──  webpack.mix.js

Abro el archivo 2020_01_20_170852_create_img_bicicletas_table.php y en la función up() agrego los campos para mi tabla img_bicicletas, mi tabla tendrá los campos id, nombre, formato e bicicletas_id y al final mediante $table->timestamps() y $table->softDeletes() agrego los campos created_at, updated_at y deleted_at

/**
 * Run the migrations.
 *
 * @return void
 */
public function up()
{
    Schema::create('img_bicicletas', function (Blueprint $table) {
        $table->bigIncrements('id');
        $table->string('nombre');
        $table->string('formato');
        $table->integer('bicicletas_id')->references('id')->on('bicicletas')->onDelete('cascade');
        $table->timestamps();
        $table->softDeletes();
    });
}

En el código anterior he colocado la restricción CASCADE a la columna bicicletas_id:

// Al eliminar un registro, se eliminan las imagenes adjuntas a ese registro
$table->integer('bicicletas_id')->references('id')->on('bicicletas')->onDelete('cascade');

Esto significa que si un registro es eliminado de la tabla bicicletas, las imágenes que pertenecen o están relacionadas a este registro, se eliminarán de la tabla img_bicicletas, así evitamos dejar rastro de registros innecesarios en la tabla img_bicicletas.

A continuación todo el código completo del archivo 2020_01_20_170852_create_img_bicicletas_table.php

<?php

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

class CreateImgBicicletasTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('img_bicicletas', function (Blueprint $table) {
            $table->bigIncrements('id');
            $table->string('nombre');
            $table->string('formato');
            $table->integer('bicicletas_id')->references('id')->on('bicicletas')->onDelete('cascade');
            $table->timestamps();
            $table->softDeletes();
        });
    }

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

Ahora ejecuto el siguiente comando para ejecutar la migración y crear la tabla img_bicicletas en la base de datos

php artisan migrate 

Migrating: 2020_01_20_170852_create_img_bicicletas_table
Migrated:  2020_01_20_170852_create_img_bicicletas_table (0.16 seconds)

Con esto he creado la tabla img_bicicletas, en esta tabla insertaré el nombre de las imágenes y en la columna bicicletas_id de esta tabla insertaré el id de un registro o bicicleta, de esta manera creo una relación de uno a muchos.

Bien hasta aquí he dejado listo Laravel, Bootstrap y la Base de Datos para en el siguiente capitulo entrar a crear el código necesario para este Proyecto.

Ten Paciencia, lo que quiero es que entiendas todo el proceso para Crear este Proyecto y no llenarte el capitulo de mucho contenido porque te puedes marear y no tendrás un óptimo aprendizaje.  

Nota (s)

  • En el siguiente capitulo crearé el Controlador, Modelo y demás elementos necesarios.
  • En esta primera Parte he desplegado todos los elementos que necesitaré para llevar a cabo mi Proyecto.

 

Síguenos en nuestras Redes Sociales para que no te pierdas nuestros próximos contenidos.