Subir imágenes es una tarea muy común en la web, pero debes considerar donde vas a guardar dichas imágenes. Cargarlos en tu servidor no suele ser la mejor opción. La mejor alternativa es subirlos a un servicio de hosting de imágenes. ImgBB es un servicio de hosting de imágenes gratuito que cuenta con un API muy sencillo de integrar con tu proyecto Laravel.
En este artículo construiremos un pequeño proyecto Laravel en el que cubriremos los pasos necesarios y de forma sencilla para usar ImgBB API.
La aplicación contará con un formulario que nos permitirá cargar una imagen y ponerle un nombre. Una vez enviado el formulario, el API de ImgBB subirá la imagen a nuestra cuenta y nos retornará un enlace. Este enlace y el nombre serán guardados en una tabla de nuestra base de datos. Finalmente extraeremos los datos de la tabla para mostrar la imagen y el título en una galería de imágenes.
Crear cuenta en ImgBB
Lo primero, dirígete a imgbb.com y regístrate con una cuenta gratuita. Una vez que hayas iniciado sesión podrás comenzar a subir imágenes directamente, pero lo que nos interesa es obtener el API KEY para poder subir nuestra imagen por medio de nuestra app. Ve al menú "Acerca" que está en la parte superior izquierda de la pantalla y elige la opción API.
Ahora puedes ver el campo con el API KEY que utilizaremos en nuestra aplicación. El siguiente paso es crear nuestro proyecto Laravel.
Instalación y configuración del proyecto Laravel
Corremos el comando para instalar nuestro proyecto. Yo lo llamé tutorial-laravel-imgbb.
composer create-project laravel/laravel tutorial-laravel-imgbb
Cuando finalice la instalación entra al directorio tutorial-laravel-imgbb que se ha creado y corre el comando para instalar las dependencias de NPM.
npm install
Ahora debemos traer el package que nos permitirá usar el API KEY de ImgBB. Lo instalamos con el siguiente comando.
composer require 101infotech/imgbb
Luego hacemos un publish de los archivos de configuración del package que acabamos instalar.
php artisan vendor:publish --tag="ImgBB"
Finalmente, busca el archivo de variables de entorno ".env", creamos una nueva variable "IMGBB_API_KEY" y pegamos el API KEY que vimos anteriormente.
Ya tenemos todo listo para comenzar a escribir un poco de código. A continuación seguimos con la creación de las vistas y agregaremos un poco de estilos.
Creación del formulario
Dentro del directorio views creamos un archivo home.blade.php
, que tendrá nuestro formulario. Corre el comando para iniciar el servidor de desarrollo.
npm run dev
Colocamos el formulario y agregamos las clases para los estilos.
<main class="bg-slate-900">
<section class="h-[100vh] flex justify-center items-center">
<section class="w-full max-w-[400px] p-3">
<h1 class="text-3xl text-stone-300 text-center py-10">Tutorial de Laravel e ImgBB</h1>
<form action="" method="post" enctype="multipart/form-data">
@csrf
<img src="https://fakeimg.pl/350x350/?text=500x500" class="w-[150px] h-auto mx-auto mb-10 rounded" id="preview-img">
<label class="block mb-10">
<span class="sr-only">Choose File</span>
<input type="file" class="block w-full text-sm text-gray-500 file:mr-4 file:py-2 file:px-4 file:rounded-full file:border-0 file:text-sm file:font-semibold file:bg-indigo-900 file:text-stone-300 hover:file:bg-sky-800 hover:file:cursor-pointer"
id="fileinput" name="fileimage"/>
</label>
<input type="text" name="title" id="title" placeholder="Name image" class="block w-full p-2 mb-10 bg-transparent border-indigo-900 border-b-2 outline-0 focus:border-sky-800 text-stone-300">
<input type="submit" value="Enviar" class="text-center bg-indigo-900 hover:bg-sky-800 text-stone-300 p-3 rounded-xl cursor-pointer block w-full">
</form>
</section>
</section>
</main>
Hasta aquí nada nuevo. El formulario tiene tres input. El primer input es de tipo file
, con el que cargaremos nuestra imagen, tiene el atributo name
con el valor fileimage
. El segundo input es de tipo text
, para el título que le daremos a la imagen, tiene el atributo name
con el valor title
. El tercer input es de tipo submit
que es el que envía el formulario. También tenemos una etiqueta <img>
para la vista previa de nuestra imagen. Antes de la etiqueta de cierre del body agregamos un script JS para actualizar la vista previa cuando elegimos la imágen que vamos a subir.
<script>
const fileinput = document.querySelector("#fileinput");
fileinput.addEventListener("change", function (e) {
const target = e.target.files[0];
const previewimg = document.querySelector("#preview-img");
previewimg.src = URL.createObjectURL(target);
}, false);
</script>
Analicemos lo que hace este script. La primer línea selecciona el input de tipo file
por medio de su atributo id
, y lo guarda en la const fileinput
. En la segunda línea adjunta al fileinput
una escucha de eventos para el evento change
. Esto significa que cuando se produzca algún cambio en el elemento, el evento change
lo detectará y entonces despachará la función. Dentro de la función vemos la línea e.target.files[0]
, esto le da acceso al archivo seleccionado y lo guarda en la const target
. Luego selecciona el elemento img
por medio de su atributo id="preview-img"
y lo carga en la const previewimg
. Finalmente actualiza el atributo src
de la vista previa con el método estático URL.createObjectURL(target)
y pasando como parámetro el target
.
A continuación crearemos el componente para la galería.
Galería de imágenes
Para la galería utilizaremos un componente anónimo. Dentro del directorio views añadimos un directorio components
y dentro creamos un archivo galeria.blade.php
.
<section class="p-4 max-w-[960px] mx-auto grid grid-cols-1 gap-4 justify-items-center sm:grid-cols-2 lg:grid-cols-3">
@for ($i = 0; $i < 6; $i++)
<div class="bg-red-500 w-[300px] h-[300px] sm:even:justify-self-start sm:odd:justify-self-end lg:even:justify-self-auto lg:odd:justify-self-auto flex justify-center items-center text-white last:bg-sky-500">
<figure class="relative">
<img src="https://fakeimg.pl/500x500/?text=IMG" alt="image" class="w-full h-auto">
<figcaption class="absolute bg-black/75 bottom-0 left-0 w-full p-4">IMAGE {{ $i + 1 }}</figcaption>
</figure>
</div>
@endfor
</section>
Con el código anterior queda formateado una grilla de imágenes que por ahora utiliza imágenes generadas por fakeimg.pl, mas tarde modificaremos esta vista para mostrar las imágenes que cargamos a nuestra cuenta imgbb.
Insertamos el componente a la vista principal home
justo antes de la etiqueta de cierre <main/>
como sigue.
<section>
<h3 class="text-xl text-stone-300 text-center pb-4">GALERÍA</h3>
</section>
<x-galeria />
Por ahora hemos terminado con las vistas, lo que sigue es conectar la app a la base de datos, crear el modelo y la migración de la tabla que guardará los datos de las imágenes.
Base de datos
Para la base de datos vamos a usar MySQL. Ingresa a tu gestor de base de datos y crea uno. Yo estoy utilizando phpMyAdmin. A la base de datos lo llamé tutorial_imgbb
.
Ve al archivo de variables de entorno .env
, busca la variable DB_DATABASE
y coloca el nombre que le diste a tu base de datos.
DB_DATABASE=tutorial_imgbb
Ya estamos conectados, ahora crearemos el modelo y la migración de la tabla images
.
Modelo y migración
Para generar el modelo y la migración de Images
ejecutamos el siguiente comando.
php artisan make:model Image -m
Este comando generará dos ficheros. El fichero del modelo se encuentra el el directorio app/models/Image.php
. Aquí colocamos los atributos que serán "mass assignable". El modelo quedará como sigue.
class Image extends Model
{
use HasFactory;
protected $fillable = ['title', 'url'];
}
Ahora la migración. El fichero se encuentra en database/migrations/create_images_table.php
. Dentro de la función up()
añadimos los campos title
y url
. La función quedará como sigue.
public function up()
{
Schema::create('images', function (Blueprint $table) {
$table->id();
$table->string('title');
$table->string('url');
$table->timestamps();
});
}
Ahora corremos las migraciónes.
php artisan migrate
Este comando debe insertar la tabla images
en la base de datos tutorial_imgbb
, con la estructura definida en la migración.
A continuación generaremos los controladores y definiremos las rutas.
Controladores
Nuestra aplicación tendrá un solo controlador, ImageController.php
. Lo generamos con el siguiente comando.
php artisan make:controller ImageController
El controlador generado se insertará en el directorio app/Http/Controllers/ImageController.php
. Abrimos el fichero y vamos a crear primero la función save()
que se encargará de subir la imagen a nuestra cuenta imgbb.com
y guardará los datos en la tabla images
.
public function save(Request $request)
{
$data = ImgBB::image($request->file('fileimage'));
$image = new Image();
$image->title = $request->title;
$image->url = $data['data']['url'];
$image->save();
return redirect()->route('home');
}
Veamos que sucede aquí. En la primer línea podemos ver en acción el package ImgBB
que habíamos instalado y configurado. Esta sencilla línea de código se encarga de subir la imagen a nuestra cuenta. La función ImgBB::image()
recibe como parámetro la imagen que queremos subir. Accedemos a dicha imagen por medio del método file
de la instancia de la clase Request
($request->file()
). El string
que recibe este método debe coincidir con el atributo name
del input file
del formulario.
En la siguiente línea creamos una instancia del modelo Image
. Establecemos el atributo title
accediendo por medio de la instancia de $request->title
. Para establecer el atributo url
usamos $data
. El método ImgBB::image()
sube la imagen y retorna un array
con un conjunto de datos. El dato que nos interesa está en $data['data']['url']
. A continuación llamamos el método save()
para guardar los datos en la tabla images
.
Finalmente, la última línea hace un redireccionamiento hacia la misma vista home
.
Debajo del método save()
añadimos la función show()
e insertamos el siguiente código.
public function show()
{
$data = Image::all();
return view('home', ['images' => $data]);
}
Este código es muy sencillo. En primer lugar el método Image::all()
recupera todos los registros de la tabla images
y los guarda en la variable $data
. La línea siguiente hace un llamado a la vista home
y le pasa la variable $data
.
Continuamos definiendo las rutas.
Rutas
Para este ejemplo vamos definir solo dos rutas. Accedemos al fichero routes/web.php
e insertamos el siguiente código.
Route::get('/', [ImageController::class, 'show'])->name('home');
Route::post('/', [ImageController::class, 'save'])->name('save-image');
La primer línea define una petición GET
y lo vincula al método show
de la clase ImageController
que definimos anteriormente. Nombramos esta ruta con el nombre home
.
La segunda línea realiza una petición POST
y lo enlaza al método save
del controlador ImageController
. Lo nombramos save-image
.
Regresamos a las vista para terminar con algunos detalles para finalizar.
Últimos detalles
En la vista home
buscamos el atributo action
del formulario y lo vinculamos la ruta POST
. Debe quedar action='{{ route("save-image") }}'
.
Más abajo en la sección de la galería agregamos una condición para verificar si hay registros o no.
@if($images->isNotEmpty())
<section>
<h3 class="text-xl text-stone-300 text-center pb-4">GALERÍA</h3>
</section>
<x-galeria :images="$images"/>
@endif
Como se observa en la código anterior, al componente galería le pasamos la variable $images
para que los datos estén disponibles dentro del componente.
Ahora en el componente galeria
debemos establecer que variables estarán disponibles dentro de este componente por medio de la directiva @props
.
@props(['images'])
Finalmente modificamos el bucle for
por un foreach
para recorrer la variable de $images
que recordemos es un array
con los registros de la tabla images
. El componente debe quedar como se muestra a continuación.
@props(['images'])
<section class="p-4 max-w-[960px] mx-auto grid grid-cols-1 gap-4 justify-items-center sm:grid-cols-2 lg:grid-cols-3">
@foreach ($images as $image)
<div class="bg-red-500 w-[300px] h-[300px] sm:even:justify-self-start sm:odd:justify-self-end lg:even:justify-self-auto lg:odd:justify-self-auto flex justify-center items-center text-white last:bg-sky-500">
<figure class="relative">
<img src="{{ $image->url }}" alt="image" class="w-full h-auto">
<figcaption class="absolute bg-black/75 bottom-0 left-0 w-full p-4">{{ $image->title}}</figcaption>
</figure>
</div>
@endforeach
</section>
El bucle recorre los registros que están en $images
y guarda cada fila en $image
. Remplazamos el valor del atributo src
de <img>
con $image->url
para acceder a dirección de la imagen, luego en la etiqueta <figcaption>
mostramos el título de la imagen a través de $image->title
.
Ahora nuestra app es completamente funcional. Debes poder cargar una imagen, subirla a cuenta imgbb y mostrarlas en tu galería.
Para terminar, sería genial tener alguna notificación que nos avise cuando la imagen ha sido subida y guardada. Pues, para ello existe un package genial que se integra muy bien con proyectos Laravel, PHPFlasher.
PHPFlasher
PHPFlasher es un poderoso sistema de notificaciones para PHP. Para integrarlo a nuestro proyecto lo instalamos con el siguente comando.
composer require php-flasher/flasher-laravel
PHPFlasher cuenta con un conjunto de diversas notificaciones. Para nuestra app elegí SweetAlert 2. Para usarlo debemos instalar el correspondiente adaptador para Laravel.
composer require php-flasher/flasher-sweetalert-laravel
Está listo para usarlo. Abrimos nuestro controlador ImageController
y al método save
le pasamos una instancia SweetAlertFactory
y luego llamamos al método addSuccess
.
<?php
namespace App\Http\Controllers;
use App\Models\Image;
use Flasher\SweetAlert\Prime\SweetAlertFactory;
use Illuminate\Http\Request;
use Infotech\ImgBB\ImgBB;
class ImageController extends Controller
{
public function save(Request $request, SweetAlertFactory $flasher)
{
$data = ImgBB::image($request->file('fileimage'));
$image = new Image();
$image->title = $request->title;
$image->url = $data['data']['url'];
$image->save();
$flasher->addSuccess("La imágen ha sido guardado con éxito!");
return redirect()->route('home');
}
public function show()
{
$data = Image::all();
return view('home', ['images' => $data]);
}
}
Una vez que la imagen suba a nuestra cuenta imgbb y guarde los datos en la tabla images
se disparará una notificación con el texto que le pasamos al método addSuccess
.
Conclusión
Hemos concluido con el proyecto. Pudimos comprobar los fácil que es usar ImgBB API e integrarlo a un proyecto Laravel. Logramos subir nuestras imágenes, guardar los datos en nuestra base de datos y mostrarlos en una sencilla galería.
El proyecto estará en mi repositorio de GitHub, puedes encontrarlo haciendo clic AQUÍ.
Espero que lo hayas encontrado entretenido, instructivo y claro. Si tienes alguna duda, puedes hacérmelo saber en los comentarios. Pronto estaré subiendo más tutoriales.
Nos vemos en la próxima. Saludos!👋😊