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

Demo

En este Post continuaremos con la Parte anterior llamada Como crear un CRUD con Galería de Imágenes en Laravel 6.2 y Bootstrap 4 – Parte 1 en donde creamos el proyecto para este tutorial, instalamos Bootstrap 4 con sus dependencias respectivas y creamos la Base de Datos para el sistema CRUD, en esta Parte 2 crearemos los modelos, el controlador y otros detalles, vamos con este Post.

Partes

Antes de continuar con este Post, te invito a escuchar el Podcast: “Donde buscar ayuda sobre Programación”:

Spotify:

Sound Cloud:

Bien ahora continuemos con el Post: Como crear un CRUD con Galería de Imágenes en Laravel 6.2 y Bootstrap 4 – Parte 2.

Para poder acceder a los datos que se encuentra en la Base de Datos, vamos a crear un modelo, luego para unir el modelo y las vista del sistema CRUD, vamos a crear un controlador, el cual se encargará de esto.

Modelos

En la Parte 1 de este tutorial creamos 2 tablas, por ende voy a necesitar crear 2 modelos, uno se llamará Bicicletas y otro Imgbicicletas.

Bicicletas

Voy a crear un modelo llamado Bicicletas, para esto ejecuto el siguiente comando:

php artisan make:model Bicicletas 

Model created successfully.

Tras ejecutar el  comando anterior, se me ha creado un archivo llamado Bicicletas.php en app > Bicicletas.php

/miproyecto
├── /app 
    ├── /Console
    ├── /Exceptions 
    ├── /Http
    ├── /Providers 
    ├── Bicicletas.php // Se ha creado este Archivo 
    ├── User.php 
├── /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

Abro el archivo Bicicletas.php que acabo de crear y agrego lo siguiente (En el código he colocado comentarios para explicar que hace cada línea de código):

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Bicicletas extends Model
{
    // Instancio la tabla 'bicicletas' 
    protected $table = 'bicicletas';
    
    // Declaro los campos que usaré de la tabla 'bicicletas' 
    protected $fillable = ['nombre', 'precio', 'stock', 'imagenes', 'url'];

    // Relación One to Many (Uno a muchos), un registro puede tener muchas imágenes 
    public function imagenesbicicletas()
    {
        return $this->hasMany('App\Imgbicicletas');
    }

}

Al final del modelo puedes ver que he creado una relación One to Many (Uno a muchos) ya que un registro puede tener muchas imágenes.

Imgbicicletas

Voy a crear un modelo llamado Imgbicicletas, para esto ejecuto el siguiente comando:

php artisan make:model Imgbicicletas 

Model created successfully.

Tras ejecutar el  comando anterior, se me ha creado un archivo llamado Imgbicicletas.php en app > Imgbicicletas.php

/miproyecto
├── /app 
    ├── /Console
    ├── /Exceptions 
    ├── /Http
    ├── /Providers 
    ├── Bicicletas.php
    ├── Imgbicicletas.php // Se ha creado este Archivo 
    ├── User.php 
├── /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

Abro el archivo Imgbicicletas.php que acabo de crear y agrego lo siguiente (En el código he colocado comentarios para explicar que hace cada línea de código):

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Imgbicicletas extends Model
{
    // Instancio la tabla 'img_bicicletas' 
    protected $table = 'img_bicicletas';
    
    // Declaro los campos que usaré de la tabla 'img_bicicletas' 
    protected $fillable = ['nombre', 'formato', 'bicicletas_id'];

    // Relación Inversa (Opcional)
    public function bicicleta()
    {
    	return $this->belongsTo('App\Bicicletas');
    }

    
}

Al final del modelo puedes ver que he creado una relación inversa belongsTo (Pertenece a), esta es opcional y es lo inverso a One to Many.

Controlador

Ahora voy a crear el controlador de mi sistema CRUD, este lo crearé ejecutando el siguiente comando:

php artisan make:controller BicicletasController 

Controller created successfully.

Después de ejecutar el comando anterior, se me ha creado un archivo llamado BicicletasController.php en app > Http > Controllers > BicicletasController.php

/miproyecto
├── /app 
    ├── /Console
    ├── /Exceptions 
    ├── /Http
        ├── /Controllers
            ├── /Auth 
            ├── Controller.php 
            ├── HomeController.php 
            ├── BicicletasController.php // Se ha creado este Archivo 
        ├── /Middleware 
        ├── /Requests
        ├── Kernel.php 
    ├── /Providers
    ├── Bicicletas.php 
    ├── User.php 
├── /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

Abro el archivo BicicletasController.php y empezaré agregado los siguientes Traits:

namespace App\Http\Controllers;

use App\Bicicletas;
use App\Imgbicicletas;
use Session;
use Redirect;
use App\Http\Requests;
use App\Http\Controllers\Controller;
use App\Http\Requests\ItemCreateRequest;
use App\Http\Requests\ItemUpdateRequest;
use Illuminate\Support\Facades\Validator;
use DB;
use Input;
use Storage; 
use Illuminate\Support\Str; 
use File; 

class BicicletasController extends Controller
{
    // Acá el código del Controlador 
}

Ahora después de los Traits, colocaré dentro de mi clase BicicletasController, el código con las operaciones CRUD (Create, Read, Update y Delete), en el código explico con comentarios, que hace cada parte de la línea de código:

<?php

namespace App\Http\Controllers;

use App\Bicicletas;
use App\Imgbicicletas;
use Session;
use Redirect;
use App\Http\Requests;
use App\Http\Controllers\Controller;
use App\Http\Requests\ItemCreateRequest;
use App\Http\Requests\ItemUpdateRequest;
use Illuminate\Support\Facades\Validator;
use DB;
use Input;
use Storage;
use Illuminate\Support\Str;
use File;

class BicicletasController extends Controller
{
    // Leer Registros (Read) 
    public function index()
    {
    	$bicicletas = Bicicletas::select('id', 'nombre', 'precio', 'stock', 'imagenes', 'url')->with('imagenesbicicletas:nombre')->get();

        //$ib = Bicicletas::find(3)->imagenesbicicletas;

        //dd($ib);

        // $imagenes = Bicicletas::find(3)->imagenesbicicletas;

        return view('admin.bicicletas.index', compact('bicicletas')); 
    }

    // Crear un Registro (Create) 
    public function crear()
    {
        $bicicletas = Bicicletas::all();
        return view('admin.bicicletas.crear', compact('bicicletas'));
    }

    // Proceso de Creación de un Registro 
    public function store(ItemCreateRequest $request)
    {
        $bicicletas= new Bicicletas;
        $bicicletas->nombre = $request->nombre;
        $bicicletas->precio = $request->precio;
        $bicicletas->stock = $request->stock;
        $bicicletas->imagenes = date('dmyHi');
        $bicicletas->url = Str::slug($request->nombre, '-');  // Acá generamos la URL amigable a partir del nombre y la guardamos en la Base de Datos

        $bicicletas->save();

        $ci = $request->file('img');

        // Validamos que el nombre y el formato de imagen esten presentes, tu puedes validar mas campos si deseas 
        $this->validate($request, [

            'nombre' => 'required',
            'img.*' => 'image|mimes:jpeg,png,jpg,gif,svg|max:2048'

        ]);        

        // Recibimos una o varias imágenes y las guardamos en la carpeta 'uploads'
        foreach($request->file('img') as $image)
            {
                $imagen = $image->getClientOriginalName();
                $formato = $image->getClientOriginalExtension();
                $image->move(public_path().'/uploads/', $imagen);

                // Guardamos el nombre de la imagen en la tabla 'img_bicicletas'
                DB::table('img_bicicletas')->insert(
				    [
				    	'nombre' => $imagen, 
				    	'formato' => $formato,
				    	'bicicletas_id' => $bicicletas->id,
				    	'created_at' => date("Y-m-d H:i:s"),
				    	'updated_at' => date("Y-m-d H:i:s")
				    ]
				);

            }         

        // Redireccionamos con mensaje 
        return redirect('admin/bicicletas')->with('message','Guardado Satisfactoriamente !');
    }

    // Leer un Registro específico (Leer)
    public function show($id)
    {
        //
    }

    //  Actualizar un registro (Update)
    public function actualizar($id)
    {
        $bicicletas = Bicicletas::find($id);

        $imagenes = Bicicletas::find($id)->imagenesbicicletas;

        return view('admin/bicicletas.actualizar', compact('imagenes'), ['bicicletas' => $bicicletas]);
    }

    // Proceso de Actualización de un Registro (Update)
    public function update(ItemUpdateRequest $request, $id)
    {        
        $bicicletas= Bicicletas::find($id);
        $bicicletas->nombre = $request->nombre;
        $bicicletas->precio = $request->precio;
        $bicicletas->stock = $request->stock;
        
        $bicicletas->save();

        $ci = $request->file('img');

        // Si la variable '$ci' no esta vacia, actualizamos el registro con las nuevas imágenes
        if(!empty($ci)){

            // Validamos que el nombre y el formato de imagen esten presentes, tu puedes validar mas campos si deseas 
            $this->validate($request, [

                'nombre' => 'required',
                'img.*' => 'image|mimes:jpeg,png,jpg,gif,svg|max:2048'

            ]);        

            // Recibimos una o varias imágenes y las actualizamos 
            foreach($request->file('img') as $image)
                {
                    $imagen = $image->getClientOriginalName();
                    $formato = $image->getClientOriginalExtension();
                    $image->move(public_path().'/uploads/', $imagen);

                    // Actualizamos el nuevo nombre de la(s) imagen(es) en la tabla 'img_bicicletas'
                    DB::table('img_bicicletas')->insert(
                        [
                            'nombre' => $imagen, 
                            'formato' => $formato,
                            'bicicletas_id' => $bicicletas->id,
                            'created_at' => date("Y-m-d H:i:s"),
                            'updated_at' => date("Y-m-d H:i:s")
                        ]
                    );

                } 

        }

        // Redireccionamos con mensaje  
        Session::flash('message', 'Editado Satisfactoriamente !');
        return Redirect::to('admin/bicicletas');
    }

    // Eliminar un Registro
    public function eliminar($id)
    {
        $bicicletas = Bicicletas::find($id);

        // Selecciono las imágenes a eliminar 
        $imagen = DB::table('img_bicicletas')->where('bicicletas_id', '=', $id)->get();        
        $imgfrm = $imagen->implode('nombre', ',');  
        //dd($imgfrm);        

        // Creamos una lista con los nombres de las imágenes separadas por coma
        $imagenes = explode(",", $imgfrm);
        
        // Recorremos la lista de imágenes separadas por coma
        foreach($imagenes as $image){
            
            // Elimino la(s) imagen(es) de la carpeta 'uploads'
            $dirimgs = public_path().'/uploads/'.$image;
            
            // Verificamos si la(s) imagen(es) existe(n) y procedemos a eliminar  
            if(File::exists($dirimgs)) {
                File::delete($dirimgs);                
            }

        }    

        
        // Borramos el registro de la tabla 'bicicletas'
        Bicicletas::destroy($id); 

        // Borramos las imágenes de la tabla 'img_bicicletas' 
        $bicicletas->imagenesbicicletas()->delete();

        // Redireccionamos con mensaje 
        Session::flash('message', 'Eliminado Satisfactoriamente !');
        return Redirect::to('admin/bicicletas');
    }

    // Eliminar imagen de un Registro
    public function eliminarimagen($id, $bid)
    {
        $bicicletas = Imgbicicletas::find($id);

        $bi = $bid;

        // Elimino la imagen de la carpeta 'uploads'
        $imagen = Imgbicicletas::select('nombre')->where('id', '=', $id)->get();
        $imgfrm = $imagen->implode('nombre', ', ');
        //dd($imgfrm);
        Storage::delete($imgfrm);

        Imgbicicletas::destroy($id);

        // Redireccionamos con mensaje 
        Session::flash('message', 'Imagen Eliminada Satisfactoriamente !');
        return Redirect::to('admin/bicicletas/actualizar/'.$bi.'');
    }

    // Detalles del Producto
    public function detallesproducto($id)
    {
        // Seleccionar un registro por su 'id' 
        $bicicletas = Bicicletas::where('id','=', $id)->firstOrFail();

        // Seleccionamos las imágenes por su 'id' 
        $imagenes = Bicicletas::find($id)->imagenesbicicletas;

        return view('admin/bicicletas.detallesproducto', compact('bicicletas', 'imagenes'));
    }

}

Bien en esta Parte 2, hemos creado el Controlador que procesará las tareas CRUD y los Modelos que me permitirá acceder a los datos de la tabla bicicletas e img_bicicletas de la Base de Datos.

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 la siguiente Parte de este Tutorial crearemos las rutas y las primeras vistas del sistema CRUD, entre otros detalles.
  • No olvides que debemos usar la Tecnología para hacer cosas Buenas por el Mundo. 

 

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