CRUD - Cadastrar, listar, editar e apagar com Laravel 11 - Parte 1
Neste tutorial, será apresentado como criar formulários de cadastro e edição, além de criar as páginas de listagem e visualização, e o botão de apagar, com Laravel 11.
Primeiramente, será demonstrado como criar o formulário para cadastrar usuários no banco de dados.
Em seguida, será explicado como criar a página para listar os registros do banco de dados, incluindo a paginação.
Por fim, será mostrado como integrar o framework Bootstrap no Laravel com Vite.
Download do código fonte desenvolvido na aula: Download
PlayList sobre Laravel 11: Acessar
Como usar SweetAlert2: Acessar
Receber as aulas gratuitas do curso de Laravel: Acessar
Para começar, é criado o projeto com Laravel 11 usando o Composer.
composer create-project laravel/laravel .
Alteradas as informações do projeto no arquivo .env.
APP_NAME=Celke
APP_ENV=local
APP_DEBUG=true
APP_TIMEZONE=America/Sao_Paulo
APP_URL=http://127.0.0.1:8000
APP_LOCALE=pt-BR
Também alteradas as credenciais do banco de dados no arquivo .env.
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=celke
DB_USERNAME=root
DB_PASSWORD=
Com as credenciais do banco de dados corretas no arquivo .env, é necessário executar as migrations que são criadas por padrão no Laravel.
php artisan migrate
Em seguida, no arquivo 'routes/web.php', é criada a rota para a página que lista os usuários.
Route::get('/', [UserController::class, 'index'])->name('user.index');
Criada a controller UserController.
php artisan make:controller UserController
Nela, é implementado o método index para recuperar os registros do banco de dados e também carregar a view.
public function index()
{
// Recuperar os registros do banco dados
$users = User::orderByDesc('id')->get();
// Carregar a VIEW
return view('users.index', ['users' => $users]);
}
Criada a view para listar os usuários.
php artisan make:view users/show
Nela, são listados os registros e incluído o layout 'layouts.admin'.
@extends('layouts.admin')
@section('content')
<div class="card mt-4 mb-4 border-light shadow">
<div class="card-header hstack gap-2">
<span>Listar Usuários</span>
<span class="ms-auto">
<a href="{{ route('user.create') }}" class="btn btn-success btn-sm">Cadastrar</a>
</span>
</div>
<div class="card-body">
<x-alert />
<table class="table">
<thead>
<tr>
<th scope="col">ID</th>
<th scope="col">Nome</th>
<th scope="col">E-mail</th>
<th scope="col" class="text-center">Ações</th>
</tr>
</thead>
<tbody>
@forelse ($users as $user)
<tr>
<th>{{ $user->id }}</th>
<td>{{ $user->name }}</td>
<td>{{ $user->email }}</td>
<td class="text-center">
<a href="{{ route('user.show', ['user' => $user->id]) }}"
class="btn btn-primary btn-sm">Visualizar</a>
<a href="{{ route('user.edit', ['user' => $user->id]) }}"
class="btn btn-warning btn-sm">Editar</a>
<form method="POST" action="{{ route('user.destroy', ['user' => $user->id]) }}"
class="d-inline">
@csrf
@method('delete')
<button type="submit" class="btn btn-danger btn-sm"
onclick="return confirm('Tem certeza que deseja apagar este registro?')">Apagar</button>
</form>
</td>
</tr>
@empty
@endforelse
</tbody>
</table>
</div>
</div>
@endsection
Para criar o layout 'resources/views/layouts/admin.blade.php', é acrescentada a estrutura básica do HTML e definido o local onde deve ser carregado o conteúdo das views através do @yield('content').
<!DOCTYPE html>
<html lang="pt-BR">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
@vite(['resources/sass/app.scss', 'resources/js/app.js'])
<title>Celke</title>
</head>
<body>
<header class="p-3 text-bg-primary">
<div class="container">
<div class="d-flex flex-wrap align-items-center justify-content-center justify-content-lg-start">
<a href="/" class="d-flex align-items-center mb-2 mb-lg-0 text-white text-decoration-none">
<svg class="bi me-2" width="40" height="32" role="img" aria-label="Bootstrap">
<use xlink:href="#bootstrap" />
</svg>
</a>
<ul class="nav col-12 col-lg-auto me-lg-auto mb-2 justify-content-center mb-md-0">
<li><a href="{{ route('user.index') }}" class="nav-link px-2 text-white">Home</a></li>
<li><a href="{{ route('user.index') }}" class="nav-link px-2 text-white">Usuários</a></li>
</ul>
<div class="text-end">
<button type="button" class="btn btn-outline-light me-2">Login</button>
</div>
</div>
</div>
</header>
<div class="container">
@yield('content')
</div>
</body>
</html>
O próximo passo é implementar a página com o formulário para cadastrar usuários no banco de dados. Primeiro, é criada a rota no arquivo 'routes/web.php'.
Route::get('/create-user', [UserController::class, 'create'])->name('user.create');
Em seguida, na controller 'UserController', criado o método 'show' para carregar a view com o formulário.
public function create(User $user)
{
return view('users.create');
}
Criada a view com o formulário para cadastrar usuário.
php artisan make:view users/create
Na mesma, é implementado o formulário, incluído o layout 'layouts.admin' e enviados os dados para a rota 'user.store'.
@extends('layouts.admin')
@section('content')
<div class="card mt-4 mb-4 border-light shadow">
<div class="card-header hstack gap-2">
<span>Cadastrar Usuário</span>
<span class="ms-auto d-sm-flex flex-row">
<a href="{{ route('user.index') }}" class="btn btn-info btn-sm me-1">Listar</a>
</span>
</div>
<div class="card-body">
<x-alert />
<form action="{{ route('user-store') }}" method="POST" class="row g-3">
@csrf
@method('POST')
<div class="col-md-12">
<label for="name" class="form-label">Nome</label>
<input type="text" name="name" class="form-control" id="name" placeholder="Nome completo"
value="{{ old('name') }}">
</div>
<div class="col-md-6">
<label for="email" class="form-label">E-mail</label>
<input type="email" name="email" class="form-control" id="email"
placeholder="Melhor e-mail do usuário" value="{{ old('email') }}">
</div>
<div class="col-md-6">
<label for="password" class="form-label">Senha</label>
<input type="password" name="password" class="form-control" id="password"
placeholder="Senha com no mínimo 6 caracteres" value="{{ old('password') }}">
</div>
<div class="col-12">
<button type="submit" class="btn btn-success btn-sm">Cadastrar</button>
</div>
</form>
</div>
</div>
@endsection
Os dados do formulário serão enviados para a rota 'user.store', que foi criada no arquivo 'routes/web.php'.
Route::get('/store-user', [UserController::class, 'store'])->name('user.store');
A rota chama o método 'store' da controller 'UserController', que recebe os dados, realiza a validação com a classe 'UserRequest' e salva no banco de dados.
public function store(UserRequest $request)
{
// Validar o formulário
$request->validated();
// Cadastrar o usuário no BD
User::create([
'name' => $request->name,
'email' => $request->email,
'password' => $request->password,
]);
// Redirecionar o usuário, enviar a mensagem de sucesso
return redirect()->route('user.index')->with('success', 'Usuário cadastrado com sucesso!');
}
É necessário criar a classe para validar os dados do formulário com o comando.
php artisan make:request UserRequest
No arquivo 'app/Http/Request/UserRequest', implementada a validação.
class UserRequest extends FormRequest
{
public function authorize(): bool
{
return true;
}
public function rules(): array
{
$userId = $this->route('user');
return [
'name' => 'required',
'email' => 'required|email|unique:users,email,' . ($userId ? $userId->id : null),
'password' => 'required|min:6',
];
}
public function messages(): array
{
return[
'name.required' => 'Campo nome é obrigatório!',
'email.required' => 'Campo e-mail é obrigatório!',
'email.email' => 'Necessário enviar e-mail válido!',
'email.unique' => 'O e-mail já está cadastrado!',
'password.required' => 'Campo senha é obrigatório!',
'password.min' => 'Senha com no mínimo :min caracteres!',
];
}
}
Após validar os dados e realizar o cadastro do registro no banco de dados, é criada a mensagem de sucesso e redirecionado para a página de listagem.
Para apresentar a mensagem de sucesso, é criado o componente 'alert' com o comando:
php artisan make:component alert --view
No componente criado em 'resources/views/components/alert.blade.php', foi implementado para verificar se existe uma mensagem de sucesso ou erro na validação dos dados do formulário e imprimi-la.
@if (session('success'))
<div class="alert alert-success" role="alert">
{{ session('success') }}
</div>
@endif
@if ($errors->any())
<div class="alert alert-danger" role="alert">
@foreach ($errors->all() as $error)
{{ $error }}<br>
@endforeach
</div>
@endif
Em seguida, é implementada a página para visualizar os detalhes do usuário. É necessário criar a rota.
Route::get('/show-user/{user}', [UserController::class, 'show'])->name('user.show');
Foi implementado na controller 'UserController' o método 'show', que recupera os dados do usuário e os envia para a view.
public function show(User $user)
{
return view('users.show', ['user' => $user]);
}
Criada a view com o comando.
php artisan make:view users/show
Na view criada, 'resources/views/users/show.blade.php', são impressos os dados do usuário.
@extends('layouts.admin')
@section('content')
<div class="card mt-4 mb-4 border-light shadow">
<div class="card-header hstack gap-2">
<span>Visualizar Usuário</span>
<span class="ms-auto d-sm-flex flex-row">
<a href="{{ route('user.index') }}" class="btn btn-info btn-sm me-1">Listar</a>
<a href="{{ route('user.edit', ['user' => $user->id]) }}" class="btn btn-warning btn-sm me-1">Editar</a>
<form method="POST" action="{{ route('user.destroy', ['user' => $user->id]) }}">
@csrf
@method('delete')
<button type="submit" class="btn btn-danger btn-sm me-1"
onclick="return confirm('Tem certeza que deseja apagar este registro?')">Apagar</button>
</form>
</span>
</div>
<div class="card-body">
<x-alert />
<dl class="row">
<dt class="col-sm-3">ID</dt>
<dd class="col-sm-9">{{ $user->id }}</dd>
<dt class="col-sm-3">Nome</dt>
<dd class="col-sm-9">{{ $user->name }}</dd>
<dt class="col-sm-3">E-mail</dt>
<dd class="col-sm-9">{{ $user->email }}</dd>
<dt class="col-sm-3">Cadastrado</dt>
<dd class="col-sm-9">{{ \Carbon\Carbon::parse($user->created_at)->format('d/m/Y H:i:s') }}</dd>
<dt class="col-sm-3">Editado</dt>
<dd class="col-sm-9">{{ \Carbon\Carbon::parse($user->updated_at)->format('d/m/Y H:i:s') }}</dd>
</dl>
</div>
</div>
@endsection
O próximo passo é implementar o formulário para editar o usuário. Esse conteúdo é abordado na parte 2 deste tutorial, através do link CRUD - Cadastrar, listar, editar e apagar com Laravel 11 - Parte 2.
Baixar o código-fonte completo do projeto.
Bom, era isso. Espero que o tutorial tenha sido útil!