[Tutorial] Como eu faço upload de imagens no laravel.
Olá galera, estou aqui para compartilhar e tambem para aprender, quero mostrar a forma que faço upload no laravel e queria opnião de vocês, eu trabalho com laravel 1 ano, então sou relativamente iniciante, e aprendi dessa forma.
aqui já vou assumir, que vocês sabem criar o projeto, então vou focar somente no codigo mesmo, mais caso queiram saber como eu faço tambem para a criação do projeto e ferramentas que eu uso, comentem ai.
Primeiramente , eu crio toda a parte do frontend, formularios e as rotas.
então vamos lá.
routes/web.php
<?php
use App\Http\Controllers\PerfilAssociadoController;
use Illuminate\Support\Facades\Route;
Route::get('/', [PerfilAssociadoController::class, 'index'])->name('perfil-associado.index');
Route::post('/', [PerfilAssociadoController::class, 'store'])->name('perfil-associado.store');
Então eu crio a index.blade.php
resources/view/index.blade.php
<!DOCTYPE html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Upload</title>
<!-- Fonts -->
<link rel="preconnect" href="https://fonts.bunny.net">
<link href="https://fonts.bunny.net/css?family=figtree:400,600&display=swap" rel="stylesheet" />
<link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous">
</head>
<body class="antialiased">
<div class="container">
@if (session()->has('success'))
<div class="alert alert-success alert-dismissible fade show" role="alert">
<strong>Sucesso!</strong> {{ session()->get('success') }}
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
</div>
@endif
@if (session()->has('error'))
<div class="alert alert-danger alert-dismissible fade show" role="alert">
<strong>Erro!</strong> {{ session()->get('error') }}
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
</div>
@endif
<form action="{{ route('perfil-associado.store')}}" method="POST" enctype="multipart/form-data">
@csrf
<div class="mb-3">
<label for="logo" class="form-label">{{ __('Logotipo') }}</label>
<input id="logo" type="file" name="logo" class="form-control">
@error('logo')
<span style="color:red;padding-top:4px;">{{ $message }}</span>
@enderror
</div>
<div class="mb-3">
<label for="nome" class="form-label">{{ __('Nome') }}</label>
<input id="nome" type="text" name="nome" value="{{ old('nome') }}" class="form-control" autofocus>
@error('nome')
<span style="color:red;padding-top:4px;">{{ $message }}</span>
@enderror
</div>
<div class="mb-3">
<label for="email" class="form-label">{{ __('E-mail') }}</label>
<input id="email" type="text" name="email" value="{{ old('email') }}" class="form-control" autofocus>
@error('email')
<span style="color:red;padding-top:4px;">{{ $message }}</span>
@enderror
</div>
<div class="mt-4">
<button type="submit" class="btn btn-primary">{{ __('Cadastrar') }}</button>
</div>
</form>
</div>
<div class="container mt-4">
<div class="row">
@if($perfis)
@foreach($perfis as $perfil)
<div class="col-md-4">
<div class="card" style="width: 18rem;">
<img src="{{ asset('photos/'. $perfil->logo) }}" class="card-img-top" alt="...">
<div class="card-body">
<h5 class="card-title
">{{ $perfil->nome }}</h5>
<p class="card-text">{{ $perfil->email }}</p>
@error('nome')
<span style="color:red;padding-top:4px;">{{ $message }}</span>
@enderror
</div>
</div>
</div>
@endforeach
@endif
</div>
</div>
</body>
</html>
após isso, crio o model e a migration.
php artisan make:model PerfilAssociado -m
database/migration/2024_02_27_142713_create_perfil_associados_table.php
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
public function up(): void
{
Schema::create('perfil_associados', function (Blueprint $table) {
$table->id();
$table->string('nome');
$table->string('email')->unique();
$table->string('logo')->nullable();
$table->timestamps();
});
}
public function down(): void
{
Schema::dropIfExists('perfil_associados');
}
};
App/Models/PerfilAssociado.php
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class PerfilAssociado extends Model
{
use HasFactory;
protected $fillable = [
'nome',
'email',
'logo',
];
}
pronto, agora podemos criar uma trait em
Traits/FileUploadTrait.php
<?php
namespace App\Traits;
use File;
use Illuminate\Http\Request;
trait FileUploadTrait
{
public function uploadImage(Request $request, string $inputName, ?string $oldPath = null, string $path = '/uploads'): ?string
{
if ($request->hasFile($inputName)) {
$image = $request->file($inputName);
$ext = $image->getClientOriginalExtension();
$imageName = 'media_' . uniqid() . '.' . $ext;
$destinationPath = 'photos' . $path;
$image->move($destinationPath, $imageName);
if ($oldPath && file_exists(public_path($oldPath))) {
File::delete(public_path($oldPath));
}
return $path . '/' . $imageName;
}
return null;
}
}
precisamos validar os dados, então vamos criar uma request.
php artisan make:request CreateAssociadoRequest
<?php
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
class CreateAssociadoRequest extends FormRequest
{
public function authorize(): bool
{
return true;
}
public function rules(): array
{
return [
'nome' => 'required',
'email' => 'required|unique:perfil_associados,email',
'logo' => 'max:2048|mimes:jpeg,png,jpg,gif,svg|nullable',
];
}
public function messages(): array
{
return [
'nome.required' => 'O campo Nome é obrigatório',
'email.required' => 'O campo E-mail é obrigatório',
'email.email' => 'O campo E-mail deve ser um endereço de e-mail válido',
'email.unique' => 'O campo E-mail já está cadastrado',
'logo.max' => 'O campo Logo deve ter no máximo 2MB',
'logo.mimes' => 'O campo Logo deve ser um arquivo do tipo: jpeg, png, jpg, gif, svg',
];
}
}
então eu crio a controller nesse caso, estarei mostrando um exemplo de perfil de um associado.
php artisan make:controller PerfilAssociadoController
App/Http/Controllers/PerfilAssociadoController
<?php
namespace App\Http\Controllers;
use App\Http\Requests\CreateAssociadoRequest;
use App\Models\PerfilAssociado;
use App\Traits\FileUploadTrait;
use Exception;
use Illuminate\Support\Facades\DB;
class PerfilAssociadoController extends Controller
{
use FileUploadTrait;
public function index()
{
$perfis = PerfilAssociado::get();
return view('index', compact('perfis'));
}
public function store(CreateAssociadoRequest $request)
{
try {
DB::beginTransaction();
$perfilAssociado = new PerfilAssociado();
$perfilAssociado->fill($request->validated());
$perfilAssociado->setAttribute('logo', $this->uploadImage($request, 'logo'));
$perfilAssociado->save();
DB::commit();
return redirect()->back()->with('success', 'Perfil cadastrado com sucesso!');
} catch (Exception $e) {
DB::rollback();
return redirect()->back()->with('fail', 'Falha ao cadastrar o perfil!');
}
}
}
agora não podemos esquecer, de ajustar o banco de dados, estou usando mysql.
então eu crio um banco de dados e ajusto no .env na raiz.
.env
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=tabnews
DB_USERNAME=root
DB_PASSWORD=****
pronto, agora executamos um
php artisan migrate
e se tudo correu como imaginava, já é possivel de nos cadastrar um perfil.