Como criar rapidamente um CRUD utilizando Laravel.
Não é preciso definir neste artigo o que é um CRUD, porque você já deve saber que é um recurso muito comum em qualquer sistema, contemplando as quatro operações sobre uma tabela no banco de dados. Um sistema possui diversos deles, desde um simples cadastro de clientes, até um mais complexo cadastro de produto onde envolva detalhes técnicos. Você também precisa ter noção sobre MVC, pois este artigo não irá tratar deste assunto.
O Laravel possui todos os recursos para te ajudar a criar de forma eficiente e rápida. Normalmente usamos Migrações para criar e até atualizar tabelas no banco de dados. Isso é eficiente porque, durante um desenvolvimento você precisa de meios para recriar o ambiente rapidamente até mesmo em plataformas diferentes.
Vamos criar um cadastro de clientes básico, iniciando pela criação da tabela.
Não vou entrar nos detalhes, como instalar o php, sqlite ou composer aqui, acredito que isto você já saiba fazer neste estágio e até mesmo tenha o ambiente pronto.
Para instalar um novo projeto, utilizando o composer:
composer create-project –prefer-dist "Laravel/Laravel" cadcli "5.7.*"
Este processo pode demorar um pouco. Lembrando que existe outras maneiras e até mesmo a mais simples utilizando o próprio instalador do Laravel, se você já tiver instalado:
laravel new cadcli
Quando o framework estiver pronto como novo projeto, acesse o diretório criado para verificar a estrutura de diretórios e obter acesso aos arquivos que precisam ser configurados para permitir o funcionamento da sua aplicação.
Dica: Se você utiliza o git para controle de versão, é neste momento que você inicia aqueles comandos preciosos:
git init git commit -m "Inicial commit" git push origin master
Este artigo também não cobre a instalação, nem a utilização do git.
Voltando ao objetivo, a primeira coisa a se verificar é: cadê o arquivo .env ? Verifique se este arquivo foi gerado na instalação do composer, caso contrário, você deve clonar o arquivo .env.example
Se você precisar clonar, pode fazer isso apenas por utilizar o comando:
cp .env.exemple .env
E na sequencia, gerar a chave da aplicação utilizando o comando:
php artisan key:generate
Atenção: lembre-se que o artisan é um script que está armazenado no diretório raiz da aplicação, sempre você deverá voltar ao diretório raiz ou invocar o php informando esses saltos de pastas usando o caminho relativo. Ex: php artisan ../../artisan key:generate
O arquivo .env é o arquivo que deve ser configurado com os dados de conexão, nome da aplicação e pode ser até expandido para contemplar outras configurações. Alguns sugerem certas configurações no arquivo app.php no subdiretório config. Isto vai funcionar, mas é desnecessário e pode levar configurações sensíveis como senhas para serem versionados, pois não serão ignorados pelo .gitignore. Além disso, sugiro, não adicionar este arquivo ao .gitignore, pois você fatalmente enfrentará outros problemas.
Para editar os scripts e programar, naturalmente precisa utilizar um editor de texto o mesmo uma IDE e isso, fica por sua conta, você escolhe.
Antes de iniciar a edição do arquivo .env, principalmente se você estiver utilizando plataforma Linux, faça a concessão de permissões para as pastas storage e database:
chmod 777 storages -R chmod 777 database -R
Isso vai permitir a operação do sistema sem nenhum erro de gravação de log, criação do arquivo para banco de dados, etc.
Feito isso, crie um arquivo no diretório database para nosso cadastro:
touch database/database.sqlite
O comando acima faz parte de plataformas unix/Linux ou git bash. Caso você tenha problemas com isso, saiba que é apenas criar um arquivo vazio no subdiretório database com esta identificação: database.sqlite
Agora abra o arquivo .env e encontre estas linhas:
DB_CONNECTION=mysql DB_HOST=127.0.0.1 DB_PORT=3306 DB_DATABASE=homestead DB_USERNAME=homestead DB_PASSWORD=secret
Apague todas deixando apenas DB_CONNECTION:
DB_CONNECTION=mysql
Agora substitua o valor da seguinte maneira:
DB_CONNECTION=sqlite
Não se preocupe em designar o nome do arquivo de banco de dados, porque ele já está pré-definido com padrão no arquivo database.php dentro do subdiretório config e você pode ver isso facilmente se editar o arquivo e encontrar essas linhas:
'connections' => [ 'sqlite' => [ 'driver' => 'sqlite', 'database' => env('DB_DATABASE', database_path('database.sqlite')), 'prefix' => '', 'foreign_key_constraints' => env('DB_FOREIGN_KEYS', true), ],
O helper database_path(‘database.sqlite’) irá tratar o caminho padrão como o subdiretório database e o nome já está definido como argumento deste helper, note: ‘database.sqlite’.
Contudo, você poderá sobrescrever esta configuração com um parâmetro DB_DATABASE no arquivo .env informando o caminho absoluto onde o arquivo para o banco de dados deverá ser encontrado.
DB_CONNECTION=sqlite DB_DATABASE=/absolute/path/to/database.sqlite
Feito isso, já temos o bastante para começar a criar a tabela. Para isso, vamos utilizar o artisan:
php artisan make:model Models\\Customer -m
Como você já deve saber, o Laravel é baseado na arquitura MVC e por isso contará com uma camada de modelo para tratar os dados e até as regras de negócio. Nesta etapa, estamos solicitando ao artisan criar uma classe de modelo chamada Customer, que deverá tratar a camada de dados. O parâmetro -m diz ao artisan para criar também a migração “oca”, onde iremos adicionar os comandos para gerar as colunas da tabela customer. Veja que definimos como Models\\Customer, porque originalmente o Laravel não designa por padrão um subdiretório para as classes de modelo, mas é uma boa prática defini-los aqui.
Proxima etapa será editar a migração, no meu caso foi criado a migração com nome:
2019_02_28_170837_create_customers_table.php
Esse nome segue uma convenção que deve ser respeitada, ____create__table.
Se você utilizar o artisan para criar a migração, da forma como utilizamos, não terá problemas com isso, não vou detalhar nada mais aqui por hora.
Abra o arquivo que foi criado no caminho database/migrations:
Quando você abrir o arquivo da migração, encontrará uma classe com apenas o início da construção. Verá dois métodos: up() e down() que seguindo a lógica uma faz e o outro reverte.
O método up é o que iremos trabalhar agora e ele talvez seja visto assim:
public function up() { Schema::create('customers', function (Blueprint $table) { $table->increments('id'); $table->timestamps(); }); }
Adicione as colunas a fim de que fique da seguinte forma:
public function up() { Schema::create('customers', function (Blueprint $table) { $table->increments('id'); $table->string('first_name', 45); $table->string('last_name', 45); $table->text('address')->nullable(); $table->string('email')->nullable(); $table->string('phone')->nullable(); $table->timestamps(); }); }
Para saber o que cada um destes médodos representam, não deixe de conferir: https://laravel.com/docs/5.7/migrations
Até aqui temos a definição da tabela customer. Você notou que o nome da tabela está no plural? Sim, esta é uma convecção utilizada pelo Laravel, quando você informa a criação de uma migração ou um “model” no singular, o Laravel se encarregará de transformar desta maneira. Por isso o recurso funcionará melhor com palavras no inglês.
Antes de avançar, vamos tratar uma configuração importantíssima para nosso objetivo: mass assignment. Essa configuração deve ser feito na classe modelo para permitir que dados possam ser definidos de forma massiva sendo portanto mais produtivo, a maneira de entrar com novos registros na tabela.
Então siga até o caminho app/Models e abra o arquivo Customer.php. Você vai ver tudo isso:
namespace App\Models; use Illuminate\Database\Eloquent\Model; class Customer extends Model { // }
De fato, não tem nada definido mesmo, a classe ainda está “oca”.
Então vamos definir um atributo para esta classe, identificado como fillable do tipo array, com todas colunas “preenchíveis” como o nome do atributo quer nos dizer:
namespace App\Models; use Illuminate\Database\Eloquent\Model; class Customer extends Model { protected $fillable = [ 'first_name', 'last_name', 'address', 'email', 'phone', ]; }
Isso já basta para conseguirmos gravar alguma coisa na tabela.
Mas antes, vamos executar as migrações, volte ao terminal e execute:
php artisan migrate
Você vai notar que todas as migrações do subdiretório database/migrations foram executas.
E pode sempre conferir o estado delas através do comando:
php artisan status:migrate
Poderíamos ter eliminado as outras migrações, mas por hora vamos mantê-las par uso futuro.
Já temos uma tabela e uma classe modelo definido, mas temos muito pouco para um CRUD.
Vamos avançar criando o controller que irá conter os métodos necessários para interagir com os dados.
Para isso execute o comando:
php artisan make:controller CustomersController -r
Com o parâmetro -r artisan irá criar uma classe com todos os métodos prontos para serem implementados como um CRUD.
Esse -r significa resource e por isso o controller é construídos com todos os métodos com nomes padrões para serem implementados como um recurso completo, contendo telas, operações sobre tabelas, etc.
Antes de editar esta classe do Controller, precisamos designar uma rota para seus métodos, ou actions como são chamados no caso de um “controller”. Novamente o artisan facilita a vida e você notará isso já. Abra o arquivo web.php que fica no subdiretório routes.
Veja que há uma rota de teste para exibir uma tela inicial para o framework.
Adicione apenas esta declaração ao final:
Route::resource('customers', 'CustomersController');
Essa linha se responsabiliza por adicionar todas as rotas necessárias para um ‘recurso’.
Note que o nome do método invocado na frente da Facade já diz tudo.
Para conferir que rotas são adicionadas, após salvar o arquivo, volte ao terminal e digite o comando:
php artisan route:list
Se você nunca teve contato com o Laravel, não preciso nem perguntar se você está gostando, não é?
Mas agora vai ficar melhor ainda e essa não será a única vez que direi isso!
Vamos partir para criação das actions do controller, então abra o arquivo CustomersController.php que está no caminho app/Http/Controller.
É necessário importar a classe de modelo Customer, como você vê logo a seguir:
namespace App\Http\Controllers; use Illuminate\Http\Request; use App\Models\Customer; class CustomersController extends Controller {
Muito bem, vamos adicionar um comando bem simples para exibir o que há na tabela clientes. Isso deve ser feito na action index. Faça apenas dessa maneira por enquanto:
public function index() { $customers = Customer::all(); return $customers; }
Agora, para testar no terminal digite o comando:
php artisan artisan serve
Note que o servidor embutido no php é invocado e logo em seguida informado o caminho para ser acessado no browser.
Por exemplo: http://127.0.0.1:8000
O que for apresentado alí, copie e cole no browser e você deverá receber uma tela inicial do framework.
Para testar o index, adicione o customer a frente e tecle enter: http://127.0.0.1:8000/customers/
O que deverá ser mostrado é um objeto vazio:
[]
Porque? Porque nosso banco está vazio!
Vamos criar views para adicionar cadastros novos e edita-los.
Primeiro, volte ao terminal, pare o servidor web embutido do php, e siga até o diretório resources/views para criar dois novos subdiretrórios, um chamado custormers e outro layout.
Agora no terminal mesmo, crie três arquivos vazios como você preferir, mas com os seguintes nomes e diretórios:
app.blade.php no caminho resources/views/layout form.blade.php no caminho resources/views/custormes grid.blade.php no caminho resources/views/custormes
Se para você o touch estiver funcionado, volte ao diretório raiz do projeto e você poderá criar assim:
touch resources/views/layout/app.blade.php touch resources/views/customers/form.blade.php touch resources/views/customers/grid.blade.php
A partir daí temos uma estrutura para começar a modelar as views.
No Laravel, todas as views são criadas a partir do subdiretório resources/views. Normalmente se utiliza o Blade.
Como nosso objetivo é criar um CRUD o mais rápido possível, não vou entrar em detalhes sobre o Blade aqui.
Mas você pode aprender mais sobre ele aqui: https://laravel.com/docs/5.8/blade
Vamos começar a modelar as views, por iniciar a definição do layout.
Portanto, siga até o diretório resources/views/layout e abra para edição o arquivo app.blade.php.
O arquivo certamente estará vazio, assim, vamos começar por adicionar uma extrutura básica de HTML5.
Aqui vamos definir o Bootstrap via CDN e deixar também os espaços que comportarão o título e o conteúdo.
Algo simples para não complicar desnecessariamente o foco:
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta name="csrf-token" content="{{ csrf_token() }}"> <title>@yield('title')</title> <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css"> <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js"></script> <script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js"></script> </head> <body> @yield('content') </body> </html>
Tendo o Layout, vamos criar a primeira view para listar os registros da tabela, substituindo aquela amostragem simples que temos neste momento. Então siga até o subdiretório resources/views/customers e abra para edição o arquivo grid.bade.php.
O arquivo provavelmente estará vazio, então adicione a seguinte estrutura:
@extends('layout.app') @section('title', 'Listando todos os registros') @section('content') <h1>Listagem de Clientes</h1> <hr> <div class="container"> <table class="table table-bordered table-striped table-sm"> <thead> <tr> <th>#</th> <th>Nome</th> <th>Sobrenome</th> <th>email</th> <th>telefone</th> <th> <a href="{{ route('customers.create') }}" class="btn btn-info btn-sm" >Novo</a> </th> </tr> </thead> <tbody> @forelse($customers as $customer) <tr> <td>{{ $customer->id }}</td> <td>{{ $customer->first_name }}</td> <td>{{ $customer->last_name }}</td> <td>{{ $customer->email }}</td> <td>{{ $customer->phone }}</td> <td> <a href="{{ route('customers.edit', ['id' => $customer->id]) }}" class="btn btn-warning btn-sm">Editar</a> <form method="POST" action="{{ route('customers.destroy', ['id' => $customer->id]) }}" style="display: inline" onsubmit="return confirm('Deseja excluir este registro?');" > @csrf <input type="hidden" name="_method" value="delete" > <button class="btn btn-danger btn-sm">Excluir</button> </form> </td> </tr> @empty <tr> <td colspan="6">Nenhum registro encontrado para listar</td> </tr> @endforelse </tbody> </table> </div> @endsection
Para testar esta view, temos de voltar ao controller CustomersController e alterar a action index para ficar assim:
public function index() { $customers = Customer::all(); return view('customers.grid', compact('customers')); }
E assim ficou melhor?
Você percebeu que temos um método de fallback aqui? Sim!
Caso não haja nenhum registro para listar será apresentado o que estiver entre a seção empty. Como se fosse uma mistura de foreach com if. É demais! Fala a verdade!?
Então vai ficar melhor ainda!
Vamos adicionar a view que edita e cria o registro, mas antes disso, vamos adicionar uma biblioteca conhecida como Laravel Collective para nos ajudar na criação do formulário. Para isso, siga até o terminal, se você ainda não o fez, pare o web servisse embutido no php. Então digite o comando do composer:
composer require "laravelcollective/html":"^5.7"
Depois, disso precisamos configurar os services providers e facades da biblioteca.
Para isso, vamos abrir o arquivo app.php que fica lá no subdiretório config.
Role o código até encontrar uma seção “Application Service Providers…” assim:
/* * Application Service Providers... */ App\Providers\AppServiceProvider::class, App\Providers\AuthServiceProvider::class, // App\Providers\BroadcastServiceProvider::class, App\Providers\EventServiceProvider::class, App\Providers\RouteServiceProvider::class,
Ao final adicione:
Collective\Html\HtmlServiceProvider::class,
Depois role o Código mais abaixo até encontrar logo abaixo a seção “Class Aliases”. Da mesma forma que você acabou de fazer, logo abaixo de:
'View' => Illuminate\Support\Facades\View::class,
Adicione as linhas no final:
'Form' => Collective\Html\FormFacade::class, 'Html' => Collective\Html\HtmlFacade::class,
Agora vai ser moleza! Se você quiser dominar estes recursos não deixe de conferir: https://laravelcollective.com/docs/master/html
Nesse momento, evoluímos muito, mas faltam recursos essenciais para ser um CRUD completo: adicionar novos registros e editar novos registros.
Para isso, siga até o subidiretório resources/views/customer/ e abra para editar o arquivo form.blade.php.
Este arquivo provavelmente estará vazio, então adicione estas linhas:
@extends('layout.app') @section('title', 'Registro') @section('content') <h1>Registro</h1> <hr> <div class="container"> @if(isset($customer)) {!! Form::model($customer, ['method' => 'put', 'route' => ['customers.update', $customer->id ], 'class' => 'form-horizontal']) !!} @else {!! Form::open(['method' => 'post','route' => 'customers.store', 'class' => 'form-horizontal']) !!} @endif <div class="card"> <div class="card-header"> <span class="card-title"> @if (isset($customer)) Editando registro #{{ $customer->id }} @else Criando novo registro @endif </span> </div> <div class="card-body"> <div class="form-row form-group"> {!! Form::label('first_name', 'Nome', ['class' => 'col-form-label col-sm-2 text-right']) !!} <div class="col-sm-4"> {!! Form::text('first_name', null, ['class' => 'form-control', 'placeholder'=>'Defina o nome']) !!} </div> </div> <div class="form-row form-group"> {!! Form::label('last_name', 'Sobreome', ['class' => 'col-form-label col-sm-2 text-right']) !!} <div class="col-sm-4"> {!! Form::text('last_name', null, ['class' => 'form-control', 'placeholder'=>'Defina o sobrenome']) !!} </div> </div> <div class="form-row form-group"> {!! Form::label('email', 'E-mail', ['class' => 'col-form-label col-sm-2 text-right']) !!} <div class="col-sm-8"> {!! Form::text('email', null, ['class' => 'form-control', 'placeholder'=>'Defina o email']) !!} </div> </div> <div class="form-row form-group"> {!! Form::label('phone', 'Telefone', ['class' => 'col-form-label col-sm-2 text-right']) !!} <div class="col-sm-4"> {!! Form::text('phone', null, ['class' => 'form-control', 'placeholder'=>'Defina o telefone']) !!} </div> </div> <div class="form-row form-group"> {!! Form::label('address', 'Endereço', ['class' => 'col-form-label col-sm-2 text-right']) !!} <div class="col-sm-10"> {!! Form::textarea('address', null, ['class' => 'form-control', 'placeholder'=>'Defina o endereço completo']) !!} </div> </div> </div> <div class="card-footer"> {!! Form::button('cancelar', ['class'=>'btn btn-danger btn-sm', 'onclick' =>'windo:history.go(-1);']); !!} {!! Form::submit( isset($customer) ? 'atualizar' : 'criar', ['class'=>'btn btn-success btn-sm']) !!} </div> </div> {!! Form::close() !!} </div> @endsection
Entenda que aqui está sendo feito muita coisa! por exemplo, estamos utilizando o mesmo formulário para criar o registro e atualizar um registro existente.
Para criar nosso primeiro registro, precisamos alterar duas actions em nosso controller: create e store.
Altere primeiro a create simplesmente assim:
public function create() { return view('customers.form'); }
Agora você deve estar ansioso para ver como ficou o formulário quando clicar em novo! Mas sugiro já adicionar o método store para fazer todo o ciclo. Adicione só assim por enquanto:
public function store(Request $request) { $customer = Customer::create($request->all()); if($customer) { return redirect()->route('customers.index'); } }
Se você fez tudo certo até aí, quando preencher o formulário, após salvar a página será redirecionada para a grade que lista os registros, então você verá um registro criado!
Mas se você clicar no botão editar ou excluir, imediatamente é direcionado a uma página em branco.
Isso porque os métodos não foram implementados, então não estão retornando nada.
Mas vamos começar por alterar o controller, permitindo a atualização de registros.
Vamos implementar os dois métodos edit e update.
Primeiro o edit, precisa deste código:
public function edit($id) { $customer = Customer::findOrFail($id); if ($customer) { return view('customers.form', compact('customer')); } else { return redirect()->back(); } }
Então será possível, restaurar um registro no formulário.
Se você já terminou e correu para testar não acreditando que isso iria dar certo… se surpreendeu!
Mas falta salvar a atualização. O método update, fará isso utilizando apenas esse código:
public function update(Request $request, $id) { $customer = Customer::where('id', $id)->update($request->except('_token', '_method')); if ($customer) { return redirect()->route('customers.index'); } }
Veja só! Nosso CRUD já está listando, criando e atualizando.
Falta só excluir! Então precisamos alterar agora apenas uma action no controller: destroy.
O código ficará assim:
public function destroy($id) { $customer = Customer::where('id', $id)->delete(); if ($customer) { return redirect()->route('customers.index'); } }
Demorou mais para você ler esse artigo até aqui do que implementar as quatro operações do CRUD com o Laravel, não é mesmo?
Todavia, podemos ainda dar uma pequena melhorada neste código. Podemos dizer que alcançamos nosso objetivo até aqui, mas então vêm um plus!
Existem dois problemas básicos:
Primeiro: O que acontece se encher a tela de registros? Suponhamos que tenhamos 150 registros. Quer ver como fica?
Segundo: Toda vez que uma operação é executada, nenhuma informação é passada ao usuário, simplesmente retornamos a grade de início. O que você acha disso?
Para entender e solucionar o primeiro problema:
Vamos criar estes registros com uma factory. Vá até o terminal e se o servidor … bem você já sabe.
Então digite o seguinte comando do artisan no terminal:
php artisan make:factory CustomerFactory --model=Customer
Agora vamos editar nossa fábrica criada com nome de arquivo CustomerFactory.php no caminho database/factories.
Ao abrir o arquivo você terá este conteúdo:
use Faker\Generator as Faker; $factory->define(App\Customer::class, function (Faker $faker) { return [ // ]; });
Altere para ficar assim (Atenção um pequeno detalhe: na frente de define, no primiro argumento, adicione Models entre App e Customer, para o caminho ficar correto: App\Models\Customer::class):
$factory->define(App\Models\Customer::class, function (Faker $faker) { return [ 'first_name' => $faker->firstName, 'last_name' => $faker->lastName, 'email' => $faker->email, 'phone' => $faker->phoneNumber, 'address' => $faker->address ]; });
Agora a fábrica está construída! Irá produzir um registro com dados aleatórios cada vez que for invocado.
Como é que podemos gerar 150 registros rapidamente com esta fábrica?
Vamos criar um seeder que irá semear todos os nossos registros usando a fábrica.
De volta ao terminal, utilize o seguinte comando do artisan:
php artisan make:seeder CustomersTableSeeder
Agora, siga até o subdiretório database/seeders e abra para editar o arquivo CustomersTableSeeder.php.
Você verá algo assim:
use Illuminate\Database\Seeder; class CustomersTableSeeder extends Seeder { /** * Run the database seeds. * * @return void */ public function run() { // } }
Então vamos adicionar uma instrução no método run, da seguinte forma:
public function run() { factory(App\Models\Customer::class, 150)->create(); }
O seeder já está pronto, é só isso mesmo…rs
Então retorne ao terminal e execute o comando do artisan:
php artisan db:seed --class=CustomersTableSeeder
Caso ocorrer algum erro, entre com o comando no terminal:
composer dump-autoload
E tente novamente.
Muito bem, agora temos 150 registros e note como a usabilidade da nossa ferramenta começa a ficar ruim. Para encontrar um fulano, temos de ir rolando a tela incansavelmente até enjoar!
Primeiro passo para tratar isso, seria incluir uma paginação, e como podemos fazer?
Vamos alterar no controller, o método index para uma pequena adição: substitua all() por paginate(10). Neste caso queremos que sejam listados 12 registros por página.
public function index() { $customers = Customer::paginate(12); return view('customers.grid', compact('customers')); }
Mas precisamos alterar a view grid para apresentar os botões link. Faça da seguinte maneira: logo um pouco antes da última linha @endsection, e também antes da div de fechamento (para não ficar feio), adicione:
{{ $customers->links() }}
Pronto! Isso vai melhorar bem a usabilidade da aplicação!
Porém, você gostaria de encontrar todos os nomes com determinadas letras, como faria de modo simples?
Vamos precisar alterar o view grid mais uma vez: logo abaixo da tag “hr”, adicione estas linhas para ficarem antes da tag de abertura div:
{!! Form::open(['method' => get, 'route' => 'customers.index, 'class' => 'form-horizontal']) !!} <div class="form-row form-group"> {!! Form::label('search', 'Procurar por', ['class' => 'col-sm-2 col-form-label text-right']) !!} <div class="col-sm-8"> {!! Form::text('search', isset($search) ? $search : null, ['class' => 'form-control']) !!} </div> <div class="col-sm-2"> {!! Form::submit('procurar', ['class'=>'btn btn-primary']) !!} </div> </div> {!! Form::close() !!}
Agora altere a action index do controller para esta forma:
public function index(Request $request) { if ($request->has('search')) { $search = $request->get('search'); $customers = Customer::where('first_name', 'like', "%{$search}%") ->orWhere('last_name', 'like', "%{$search}%") ->orWhere('email', 'like', "%{$search}%") ->orWhere('phone', 'like', "%{$search}%") ->orWhere('address', 'like', "%{$search}%") ->paginate(10); $customers->appends(['search' => $search]); return view('customers.grid', compact('customers', 'search')); } else { $customers = Customer::paginate(10); return view('customers.grid', compact('customers')); } }
Agora melhoramos muito a usabilidade do aplicativo, porque podemos paginar e filtrar a grade. Certamente existem outras melhorias, bem como ordenação, etc. Mas dessa forma este artigo ficará bem mais cansativo.
Segundo problema que encontramos são as interações com o usuário.
Como podemos tratar isso?
Existem muitas maneiras, mas vamos fazer de uma maneira prática: criando mais uma view e um complemento para o layout.
Precisamos de um arquivos:
Novamente se para você o touch estiver funcionado, volte ao diretório raiz do projeto e você poderá criar assim:
touch resources/views/layout/messages.blade.php
Agora abra o arquivo messages.blade.php no subdiretório resources/views/layout. O arquivo provavelmente estará vazio, então adicione este código:
@if($errors->any()) <div class="alert alert-danger"> <ul> @foreach ($errors->all() as $error) <li>{{ $error }}</li> @endforeach </ul> </div> @endif @if(Session::has('success')) <div class="alert alert-success"> {{ Session::get('success') }} </div> @endif @if(Session::has('info')) <div class="alert alert-info"> {{ Session::get('info') }} </div> @endif
Agora em vamos referenciar na view da grade e do formulário. Então siga até o subdiretório resources/views/customer.
Abra o arquivo grid.blade.php e logo abaixo da div de abertura com a classe container, inclua a seguinte instrução:
@include('layout.messages')
Faça o mesmo para o arquivo form.blade.php, logo abaixo da div de abertura com a classe container, inclua a seguinte instrução anterior.
Feito isso vamos precisar voltar a editar algumas actions de nosso controller. Antes disso, vamos configurar as validações, e o método de utilizar uma classe a parte, permitirá um código mais limpo. Então execute o seguinte comando no terminal:
php artisan make:request CustomerRequest
Agora siga para o seguinte subdiretório app/Http/Requests e abra para editar o arquivo criado CustomerRequest.php. Você verá o seguinte conteúdo:
namespace App\Http\Requests; use Illuminate\Foundation\Http\FormRequest; class CustomerRequest extends FormRequest { /** * Determine if the user is authorized to make this request. * * @return bool */ public function authorize() { return false; } /** * Get the validation rules that apply to the request. * * @return array */ public function rules() { return [ // ]; } }
A primeira coisa a se alterar nesta classe, está no método authorize, mude o retorno de false para true, senão você terá acesso negado, pois não estamos trabalhando com sistema autorização de acesso.
Em seguida, adicione mais um método vazio no final chamado messages da seguinte forma:
public function messages() { return [ // ]; }
Agora vamos configurar primeiro o método rules:
public function rules() { return [ 'first_name' => 'required|max:45', 'last_name' => 'required|max:45', ]; }
Agora o método messages (opcional) que permite customizar as mensagens de erros:
public function messages() { return [ 'first_name.required' => 'O campo nome é requerido', 'last_name.required' => 'O campo sobrenome é requerido', 'first_name.max' => 'O tamanho do nome inserido no campo não pode utltrapassar 45 caracteres', 'last_name.max' => 'O tamanho do nome inserido no campo não pode utltrapassar 45 caracteres', ]; }
Agora podemos fazer as devidas alterações no controller. Primeiro você deve importar as classes necessárias:
use Illuminate\Support\Facades\Session; use Illuminate\Support\Facades\Validator; use App\Http\Requests\CustomerRequest;
Então siga para o método store e altere para ficar da seguinte maneira:
public function store(CustomerRequest $request) { $customer = Customer::create($request->all()); if ($customer) { Session::flash('success', "Registro #{$customer->id} salvo com êxito"); return redirect()->route('customers.index'); } return redirect()->back()->withErrors(['error', "Registo não foi salvo."]); }
Agora, será necessário alterar o método update:
public function update(CustomerRequest $request, $id) { $customer = Customer::where('id', $id)->update($request->except('_token', '_method')); if ($customer) { Session::flash('success', "Registro #{$id} atualizado com êxito"); return redirect()->route('customers.index'); } return redirect()->back()->withErrors(['error', "Registo #{$id} não foi encontrado"]); }
Por fim, uma pequena alteração no método destroy:
public function destroy($id) { $customer = Customer::where('id', $id)->delete(); if ($customer) { Session::flash('success', "Registro #{$id} excluído com êxito"); return redirect()->route('customers.index'); } return redirect()->back()->withErrors(['error', "Registo #{$id} não pode ser excluído"]); }
Agora, tratamos o retorno de informações para o usuário e você pode testar isso por tentar salvar um registro sem preencher os campos nome e sobrenome ou executar alguma ação como atualizar, excluir, criar novo registro. Melhorou muito a aplicação.
Espero que este artigo possa lhe ajudar bastante no seu aprendizado com Laravel.
[]’s