19/07/2020

Criar CRUD completo PHP com Framework Laravel 7

Criar CRUD completo php com framework laravel 7

Criando CRUD Laravel

Visando facilitar a vida dos iniciantes em Laravel, postarei todos os exemplos abordados, você verá passo a passo a criação de um CRUD Laravel (Create Read Update Delete).

Pré-requisitos:

  • Ambiente de desenvolvimento instalado e configurado

Para iniciar a criação do nosso Crud Laravel, precisamos instalar uma nova aplicação do Framework

1 . Instalando Laravel 7

					
composer create-project laravel/laravel --prefer-dist crud
cd crud
composer require laravelcollective/html

2. Atualizando as configuração do banco de dados

Agora faremos a configuração do banco, nome do banco, nome de usuário, senha etc.

Para isso edite o arquivo .env:

					
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=crud
DB_USERNAME=root
DB_PASSWORD=senha

3. Criando Migration e Model

Estamos diante de uma situação sem precedentes, Pandemia do Coronavírus. Iremos cadastrar alguns dados em nosso novo sistema.

Criaremos um Model e uma Migration, com o nome Corona. Sempre deve se usar o nome no singular, assim não terá problemas e tudo irá funcionar com deve.

Com o exemplo Corona ele irá criar uma tabela com o nome coronas, e também um Model Corona:

					
php artisan make:model Corona -m

Agora você pode conferir os arquivos de migração na pasta database/migrations. Você irá encontrar os seguintes arquivos padrão e também o novo gerado com o comando anterior:

  • timestamp__create_users_table.php
  • timestamp_create_password_resets_table.php
  • timestamp_create_failed_jobs_table.php
  • timestamp_create_coronas_table.php

4. Preparando o banco de dados

edite o arquivo que acabamos de gerar timestamp_create_coronas_table.php:

					
<?php

use Illuminate\Database\Migrations\Migration; use Illuminate\Database\Schema\Blueprint; use Illuminate\Support\Facades\Schema; class CreateCoronasTable extends Migration { /** * Run the migrations. * * @return void */ public function up() { Schema::create('coronas', function (Blueprint $table) { $table->id(); $table->string('country_name'); $table->string('symptoms'); $table->integer('cases'); $table->timestamps(); }); } /** * Reverse the migrations. * * @return void */ public function down() { Schema::dropIfExists('coronas'); } }

Existem dois tipos de funções dentro dos arquivos de migração:

  • Função up() – Permite Criar/Atualizar tabelas, Colunas e Índices.
  • Função down() permite reverter uma operação feita pelo método up.

5. Configurando Model Corona

Adicione o código abaixo no arquivo app/Corona.php:

					
<?php

namespace App; use Illuminate\Database\Eloquent\Model; class Corona extends Model { protected $fillable = ['country_name', 'symptoms', 'cases']; }

Em seguida, precisamos executar o seguinte comando para criar nossa tabela no banco de dados:

6. Criando um Controller

Criaremos o controlador CoronaController.php, executando o comando:

					
php artisan make:controller CoronaController -r

Agora foi gerado um novo arquivo app/Http/Controllers/CoronaController.php. Por padrão sete métodos são definidos nele:

  • index() => Mostra uma lista de casos cadastrados
  • create() => Cria novos casos usando um formulário
  • store() => Cria novos casos no banco de dados
  • show() => Mostra um casos específico
  • edit() => Atualiza os dados dos casos usando um formulário
  • update() => Atualiza os dados dos casos no banco
  • destroy() => Remove um caso em particular

7. Configurando Controller

Edite o arquivo app/Http/Controllers/CoronaController.php:

					
<?php

namespace App\Http\Controllers; use Illuminate\Http\Request; use App\Corona; class CoronaController extends Controller { /** * Display a listing of the resource. * * @return \Illuminate\Http\Response */ public function index() { $coronacases = Corona::all(); return view('coronas.index', compact('coronacases')); } /** * Show the form for creating a new resource. * * @return \Illuminate\Http\Response */ public function create() { return view('coronas.create'); } /** * Store a newly created resource in storage. * * @param \Illuminate\Http\Request $request * @return \Illuminate\Http\Response */ public function store(Request $request) { $validatedData = $request->validate([ 'country_name' => 'required|max:255', 'symptoms' => 'required', 'cases' => 'required|numeric', ]); $show = Corona::create($validatedData); return redirect('/coronas')->with('success', 'Dados de Corona adicionado com sucesso!'); } /** * Display the specified resource. * * @param int $id * @return \Illuminate\Http\Response */ public function show($id) { $coronacase = Corona::findOrFail($id); return view('coronas.show',compact('coronacase')); } /** * Show the form for editing the specified resource. * * @param int $id * @return \Illuminate\Http\Response */ public function edit($id) { $coronacase = Corona::findOrFail($id); return view('coronas.edit', compact('coronacase')); } /** * Update the specified resource in storage. * * @param \Illuminate\Http\Request $request * @param int $id * @return \Illuminate\Http\Response */ public function update(Request $request, $id) { $validatedData = $request->validate([ 'country_name' => 'required|max:255', 'symptoms' => 'required', 'cases' => 'required|numeric', ]); Corona::whereId($id)->update($validatedData); return redirect('/coronas')->with('success', 'Dados de Corona atualizado com sucesso!'); } /** * Remove the specified resource from storage. * * @param int $id * @return \Illuminate\Http\Response */ public function destroy($id) { $coronacase = Corona::findOrFail($id); $coronacase->delete(); return redirect('/coronas')->with('success', 'Dados de Corona removido com sucesso!'); } }

8. Configurando Rotas

Edite o arquivo routes/web.php:

					
<?php
use Illuminate\Support\Facades\Route;

/*
|--------------------------------------------------------------------------
| Web Routes
|--------------------------------------------------------------------------
|
| Here is where you can register web routes for your application. These
| routes are loaded by the RouteServiceProvider within a group which
| contains the "web" middleware group. Now create something great!
|
*/

Route::get('/', function () {
    return view('welcome');
});

Route::resource('coronas', 'CoronaController');

Já pode visualizar as novas rotas usando o comando:

Lista das novas rotas criadas:

MethodURIActionRoute Name
POSTcoronasstorecoronas.store
GET|HEADcoronasindexcoronas.index
GET|HEADcoronas/createcreatecoronas.create
DELETEcoronas/{corona}destroycoronas.destroy
PUT|PATCHcoronas/{corona}updatecoronas.update
GET|HEADcoronas/{corona}showcoronas.show
GET|HEADcoronas/{corona}/editeditcoronas.edit

9. Criando Views usando Blade Templates

Para cada rota GET, precisamos criar uma visualização.

Agora, criaremos as views em resources/views/coronas:

  • create.blade.php
  • edit.blade.php
  • index.blade.php
  • layout.blade.php
  • show.blade.php

Para ganhar tempo iremos criar todas de uma só vez usando o comando:

					
mkdir resources/views/coronas

touch resources/views/coronas/create.blade.php resources/views/coronas/edit.blade.php resources/views/coronas/index.blade.php resources/views/coronas/layout.blade.php resources/views/coronas/show.blade.php

10. Configurando o layout usando Bootstrap CDN

Edite o arquivo resources/views/coronas/layout.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">

    <!-- CSRF Token -->
    <meta name="csrf-token" content="{{ csrf_token() }}">

    <title>@yield('title') - {{ config('app.name', 'i9W3b') }}</title>

    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.5.0/css/bootstrap.min.css">
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css">

    <!-- Fonts -->
    <link rel="dns-prefetch" href="//fonts.gstatic.com">
    <link href="https://fonts.googleapis.com/css?family=Nunito" rel="stylesheet">

    <style>
        .btn-group-sm>.btn, .btn-sm {
            padding: .1rem .5rem;
            font-size: .8rem;
            line-height: 1.5;
            border-radius: .2rem;
            color: #fff !important;
        }

        body {
            font-family: "Nunito", sans-serif;
            font-size: 0.9rem;
            background-color: #f8fafc;
        }
    </style>
    @stack('css')
</head>

<body>
    <div id="app">
        <nav class="navbar navbar-expand-md navbar-light bg-white shadow-sm">
            <div class="container">
                <a class="navbar-brand" href="{{ url('/') }}">
                    {{ config('app.name', 'i9W3b') }}
                </a>
                <button class="navbar-toggler" type="button" data-toggle="collapse"
                    data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false"
                    aria-label="{{ __('Toggle navigation') }}">
                    <span class="navbar-toggler-icon"></span>
                </button>

                <div class="collapse navbar-collapse" id="navbarSupportedContent">
                    <!-- Left Side Of Navbar -->
                    <ul class="navbar-nav mr-auto">

                    </ul>

                    <!-- Right Side Of Navbar -->
                    <ul class="navbar-nav ml-auto">
                        <!-- Authentication Links -->
                        @guest
                        @if (Route::has('login'))
                        <li class="nav-item">
                            <a class="nav-link" href="{{ route('login') }}">{{ __('Login') }}</a>
                        </li>
                        @endif
                        @if (Route::has('register'))
                        <li class="nav-item">
                            <a class="nav-link" href="{{ route('register') }}">{{ __('Register') }}</a>
                        </li>
                        @endif
                        @else
                        @if (Route::has('logout'))
                        <li class="nav-item dropdown">
                            <a id="navbarDropdown" class="nav-link dropdown-toggle" href="#" role="button"
                                data-toggle="dropdown" aria-haspopup="true" aria-expanded="false" v-pre>
                                {{ Auth::user()->name }} <span class="caret"></span>
                            </a>

                            <div class="dropdown-menu dropdown-menu-right" aria-labelledby="navbarDropdown">
                                <a class="dropdown-item" href="{{ route('logout') }}" onclick="event.preventDefault();
                                                     document.getElementById('logout-form').submit();">
                                    {{ __('Logout') }}
                                </a>

                                <form id="logout-form" action="{{ route('logout') }}" method="POST"
                                    style="display: none;">
                                    @csrf
                                </form>
                            </div>
                        </li>
                        @endif
                        @endguest
                    </ul>
                </div>
            </div>
        </nav>

        <main class="py-4">
            @yield('content')
        </main>
    </div>

    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.16.0/umd/popper.min.js"></script>
    <script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.5.0/js/bootstrap.min.js"></script>

    @stack('js')
</body>

</html>

Agora é só configurar as views para criar, armazenar, visualizar e validar os dados no banco de dados MySQL

11. View Create (Cria novas entradas de dados no banco)

Esses dados serão gerados usando componentes Bootstrap Form e Card UI.
Edite o arquivo resources/views/coronas/create.blade.php:

					
@extends('coronas.layout')

@section('title',__('Criar (Corona CRUD Laravel) - i9W3b'))

@push('css')
<style>
    /* Personalizar layout*/
</style>
@endpush

@section('content')
<div class="container">
    <div class="row justify-content-center">
        <div class="col-md-12">
            <div class="card">
                <div class="card-header">
                    <div class="d-flex justify-content-between w-100">
                        <span>@lang('Criar (Corona CRUD Laravel) - i9W3b')</span>
                        <a href="{{ url('coronas') }}" class="btn-info btn-sm">
                            <i class="fa fa-arrow-left"></i> @lang('Voltar')
                        </a>
                    </div>
                </div>
                <div class="card-body">
                    @if (session('success'))
                    <div class="alert alert-success" role="alert">
                        {{ session('success') }}
                    </div>
                    @endif

                    {!! Form::open(['action' =>'CoronaController@store', 'method' => 'POST'])!!}

                    <div class="form-group">
                        {!! Form::label(__('Nome do País:')) !!}
                        {!! Form::text("country_name", null ,["class"=>"form-control","required"=>"required"]) !!}
                    </div>

                    <div class="form-group">
                        {!! Form::label(__('Total de Casos:')) !!}
                        {!! Form::text("symptoms", null ,["id" => "symptoms", "class"=>"form-control mmss","required"=>"required"]) !!}
                    </div>

                    <div class="form-group">
                        {!! Form::label(__('Total de Mortes:')) !!}
                        {!! Form::text("cases", null ,["id" => "cases", "class"=>"form-control mmss","required"=>"required"]) !!}
                    </div>

                    <div class="well well-sm clearfix">
                        <button class="btn btn-success pull-right" title="@lang('Salvar')"
                            type="submit">@lang('Adicionar')</button>
                    </div>

                    {!! Form::close() !!}


                </div>
            </div>
        </div>
    </div>
</div>
@endsection

@push('js')
<script language='JavaScript'>
    $(".mmss").focusout(function () {
        var id = $(this).attr('id');
        var vall = $(this).val();
        var regex = /[^0-9]/gm;
        const result = vall.replace(regex, ``);
        $('#' + id).val(result);
    });
</script>
@endpush
CRUD Laravel, Mostrando Criando Estatísticas Coronavírus do Brasil

12. View Edit (Edita e Atualiza os dados)

Editar o arquivo resources/views/coronas/edit.blade.php:

					
@extends('coronas.layout')

@section('title',__('Editar (Corona CRUD Laravel) - i9W3b'))

@push('css')
<style>
    /* Personalizar layout*/
</style>
@endpush

@section('content')
<div class="container">
    <div class="row justify-content-center">
        <div class="col-md-12">
            <div class="card">
                <div class="card-header">
                    <div class="d-flex justify-content-between w-100">
                        <span>@lang('Editar (Corona CRUD Laravel) - i9W3b')</span>
                        <a href="{{ url('coronas') }}" class="btn-info btn-sm">
                            <i class="fa fa-arrow-left"></i> @lang('Voltar')
                        </a>
                    </div>
                </div>
                <div class="card-body">
                    @if (session('status'))
                    <div class="alert alert-success" role="alert">
                        {{ session('status') }}
                    </div>
                    @endif

                    {!! Form::open(['action' => ['CoronaController@update',$coronacase->id], 'method' => 'PUT'])!!}

                    <div class="form-group">
                        {!! Form::label(__('Nome do País:')) !!}
                        {!! Form::text("country_name", $coronacase->country_name ,["class"=>"form-control","required"=>"required"]) !!}
                    </div>

                    <div class="form-group">
                        {!! Form::label(__('Total de Casos:')) !!}
                        {!! Form::text("symptoms", $coronacase->symptoms ,["id" => "symptoms", "class"=>"form-control mmss","required"=>"required"]) !!}
                    </div>

                    <div class="form-group">
                        {!! Form::label(__('Total de Mortes:')) !!}
                        {!! Form::text("cases", $coronacase->cases ,["id" => "cases", "class"=>"form-control mmss","required"=>"required"]) !!}
                    </div>

                    <div class="well well-sm clearfix">
                        <button class="btn btn-success pull-right" title="@lang('Salvar')"
                            type="submit">@lang('Adicionar')</button>
                    </div>

                    {!! Form::close() !!}

                </div>
            </div>
        </div>
    </div>
</div>
@endsection

@push('js')
<script language='JavaScript'>
    $(".mmss").focusout(function () {
        var id = $(this).attr('id');
        var vall = $(this).val();
        var regex = /[^0-9]/gm;
        const result = vall.replace(regex, ``);
        $('#' + id).val(result);
    });
</script>
@endpush
CRUD Laravel, Mostrando Editando Estatísticas Coronavírus do Brasil

13. View Index (Lista todos os cadastros do banco de dados)

Editar arquivo resources/views/coronas/index.blade.php:

					
@extends('coronas.layout')

@section('title',__('Corona (CRUD Laravel) - i9W3b'))

@push('css')
<style>
    /* Personalizar layout*/
</style>
@endpush

@section('content')
<div class="container">
    <div class="row justify-content-center">
        <div class="col-md-12">
            <div class="card">
                <div class="card-header">
                    <div class="d-flex justify-content-between w-100">
                        <span>@lang('Corona (CRUD Laravel) - i9W3b')</span>
                        <a href="{{ url('coronas/create') }}" class="btn-primary btn-sm">
                            <i class="fa fa-plus"></i> @lang('Criar Novo')
                        </a>
                    </div>
                </div>
                <div class="card-body">
                    @if (session('success'))
                    <div class="alert alert-success" role="alert">
                        {{ session('success') }}
                    </div>
                    @endif

                    <table class="table table-bordered">
                        <thead>
                            <tr>
                                <td>ID</td>
                                <td>@lang('Nome do País')</td>
                                <td>@lang('Total de Casos')</td>
                                <td>@lang('Total de Mortes')</td>
                                <td colspan="3" class="text-center">@lang('Ações')</td>
                            </tr>
                        </thead>
                        <tbody>
                            @foreach($coronacases as $case)
                            <tr>
                                <td>{{$case->id}}</td>
                                <td>{{$case->country_name}}</td>
                                <td>{{number_format($case->symptoms,0,",",".")}}</td>
                                <td>{{number_format($case->cases,0,",",".")}}</td>
                                <td class="text-center p-0 align-middle" width="70">
                                    <a href="{{ route('coronas.show', $case->id)}}"
                                        class="btn btn-info btn-sm">@lang('Abrir')
                                    </a>
                                </td>
                                <td class="text-center p-0 align-middle" width="70">
                                    <a href="{{ route('coronas.edit', $case->id)}}"
                                        class="btn btn-primary btn-sm">@lang('Editar')
                                    </a>
                                </td>
                                <td class="text-center p-0 align-middle" width="70">
                                    <form action="{{ route('coronas.destroy', $case->id)}}" method="post">
                                        @csrf
                                        @method('DELETE')
                                        <button class="btn btn-danger btn-sm" type="submit">Delete</button>
                                    </form>
                                </td>
                            </tr>
                            @endforeach
                        </tbody>
                    </table>

                </div>
            </div>
        </div>
    </div>
</div>
@endsection

@push('js')
<script>
    // Script personalizado
</script>
@endpush
CRUD Laravel, Mostrando Estatísticas Coronavírus

14. View Show (Mostra um cadastro específico)

Editar arquivo resources/views/coronas/show.blade.php:

					
@extends('coronas.layout')

@section('title',__($coronacase->country_name . ': Corona CRUD Laravel - i9W3b'))

@push('css')
<style>
table{
font-family: Verdana,sans-serif;
border: 1px solid #ccc;
margin: 20px 0;
}

table th{
    padding:10px;
    font-weight: normal;
}
</style>
@endpush

@section('content')
<div class="container">
    <div class="row justify-content-center">
        <div class="col-md-12">
            <div class="card">
                <div class="card-header">
                    <div class="d-flex justify-content-between w-100">
                        <span><span class="text-info">{{$coronacase->country_name}}</span>: (@lang('Corona CRUD Laravel')) - i9W3b</span>
                        <a href="{{ url('coronas') }}" class="btn-info btn-sm">
                            <i class="fa fa-arrow-left"></i> @lang('Voltar')
                        </a>
                    </div>
                </div>
                <div class="card-body">
                    @if (session('success'))
                        <div class="alert alert-success" role="alert">
                            {{ session('success') }}
                        </div>
                    @endif


                    <table class="w3-table-all notranslate" width="100%" border="1">
                        <tbody>
                        <tr>
                          <th align="left"><strong>ID:</strong></th>
                          <th align="left">{{$coronacase->id}}</th>
                        </tr>
                        <tr>
                            <th align="left"><strong>@lang('Nome do País')</strong>:</th>
                            <th align="left">{{$coronacase->country_name}}</th>
                        </tr>
                        <tr>
                            <th align="left"><strong>@lang('Total de Casos')</strong>:</th>
                            <th align="left">{{$coronacase->symptoms}}</th>
                          </tr>
                          <tr>
                              <th align="left"><strong>@lang('Total de Mortes')</strong>:</th>
                              <th align="left">{{$coronacase->cases}}</th>
                          </tr>
                          <tr>
                            <th align="left"><strong>@lang('Adicionado')</strong>:</th>
                            <th align="left">{{$coronacase->created_at}}</th>
                          </tr>
                          <tr>
                              <th align="left"><strong>@lang('Atualizado')</strong>:</th>
                              <th align="left">{{$coronacase->updated_at}}</th>
                          </tr>
                        </table>

                </div>
            </div>
        </div>
    </div>
</div>
@endsection

@push('js')
<script>
    // Script personalizado
</script>
@endpush

Pronto!

Agora podemos iniciar executando:

Acessar a rota /coronas/create e começar a cadastrar os casos da pandemia no sistema:

					
http://127.0.0.1:8000/coronas/create

Ver os valores cadastrados:

Repositório somente dos arquivos criados: https://github.com/i9w3b/tutorial-crud-files

Repositório do projeto: https://github.com/i9w3b/tutorial-crud-project

Comente abaixo se conseguiu seguir os passos e se tudo funcionou como deveria!

😉

Caso tenha alguma sugestão de novas postagens também pode me contatar -> Falar com Marcelo Sena

Share

Marcelo Sena

Programador PHP e Especialista em Sistemas WEB. Atualmente trabalhando como Freelancer, e Autor/Editor nas horas vagas - blog marcelosena.com.

Você pode gostar...

2 Respostas

  1. joao soller disse:

    Muito bom parabes

Deixe uma resposta

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *

%d blogueiros gostam disto: