---
# System prepended metadata

title: Laravel
tags: [laravel, estudos, php]

---

Laravel
===

###### tags: `php` `estudos` `laravel`
# Dicas
Preenchimento do formulários com os valores digitados antes do submit
* https://laracasts.com/discuss/channels/general-discussion/keeping-input-on-form-validation-request

Reaproveitar formulário tanto para criação como edição:
* https://laracasts.com/discuss/channels/requests/keep-inputs-after-failed-validation

## Blade Docs
* https://laravel.com/docs/master/blade

## Laravel DataBase Migrations
* https://laravel.com/docs/master/migrations

## Laravel Eloquent ORM
* https://laravel.com/docs/master/eloquent

## Laravel Database
* https://laravel.com/docs/master/database


## API para testes...
https://swapi.co/

## Criacao de API baseada em arquivo json
https://github.com/typicode/json-server


## Lara Notification -> telegram...
composer require laravel-notification-channels/telegram


 ## exemplo de implementacao de jwt similar ao apresentado em aula...
 https://medium.com/@aschmelyun/securing-your-laravel-api-with-jwts-in-10-minutes-or-less-9622541244f6



# Dia 01

Para criar um projeto com Laravel:

No Linux:
`composer create-project laravel/laravel --prefer-dist projeto`


## 1 - Configurar ENV
Alterar o arquivo “.env”

### .env
```bash=
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=bdmnlar2
DB_USERNAME=root
DB_PASSWORD=coti
```
## 2 - Criar o banco...

```bash=
create database bdmnlar2;
use bdmnlar2;
```
## 3 - Criar Model
Criar uma classe...
==php artisan make:model Pessoa==

### 3.1 Pessoa.php
```php=
<?php

namespace App;

use IlluminateDatabaseEloquentModel;

class Pessoa extends Model{
    protected  $fillable= [
        'id','nome','idade'
    ];
    protected $table='pessoas'; 
}
```

## 4 - Criar Migration
Criar a base da tabela..
==php artisan make:migration pessoas==
### 4.1 - NossaMigration gerada...
```php=
<?php

use IlluminateSupportFacadesSchema;
use IlluminateDatabaseSchemaBlueprint;
use IlluminateDatabaseMigrationsMigration;

class Pessoas extends Migration{
   
    //Criando a tabela  pessoa com 3 campos ...
    public function up()    {
        
    Schema::create('pessoas', function (Blueprint $table){
        $table->increments('id');
        $table->string('nome',50);
        $table->integer('idade');
        $table->string('endereco',50)->nullable();
        $table->timestamps();
        });
    }

    public function down()    {
       Schema::drop('pessoas');
    }
}
```

### 4.2 - aplicar nossa migration (criando  a tabela no banco)
==php artisan migrate==
Forçar a execução
==php artisan migrate --force==
ou
==php artisan migrate:rollback==

Em últimos casos
==php artisan migrate:reset==
ou
==php artisan migrate:refresh --seed==

## 5 - Criar Controller
Criar o controller:
==php artisan make:controller pessoaController==

### 5.1 - PessoaController.php
```php=
<?php

namespace AppHttpControllers;

use AppPessoa;
use IlluminateHttpRequest;

class PessoaController extends Controller{

    protected $pessoas;

    public function __construct(Pessoa $pessoas)    {
        $this->pessoas = $pessoas;
    }

    //index está buscando todos os dados de pessoa
    public function index()    {
        //$pessoas = $this->pessoas->paginate(3);
        $pessoas = $this->pessoas->all();
        // olha o nome do blade aqui
        //return view('pessoas',compact('pessoas'));
        return view('pessoas', ['pessoas' => $pessoas]);
    }

    //Metodo Show (buscar pelo Codigo)
    public function show($id)    {
        //pessoa (id pre, nome pre, idade pre)
        //Eloquent
        $pessoa = $this->pessoas->find($id);
        //nomedoBlade
        return view('buscapessoa', compact('pessoa'));
    }

    //   /form ele irá entrar em Cadastrar ...

    public function create()    {
        //É uma entrada
        return view('cadastrar');
    }

    public function posts(Request $request)    {
        //resgata TUDO
        //dd($request);
        $request->validate([
            'idade' => 'required|numeric|min:18|max:150',
        ]);
        $pessoa = $request->all();

        //dd($pessoa);
        $this->pessoas->create($pessoa); //esta Gravando aqui
        return redirect()->route('listar')->
            with('success', 'Pessoa Cadastrada com Sucesso');

    }

}
```
---

## 6 - Adicionar ROTAS
Criar as rotas...

### 6.1 - web.php
```php=
Route::get('/','PessoaController@index')->name('listar');
Route::get('id/{id}','PessoaController@show')->name('buscar');
Route::get('/form','PessoaController@create')->name('formulario');
Route::post('/salvar','PessoaController@posts')->name('salvarPessoa');
```

## 7 - Criar Views VIEWs
Criar as telas (views)...
### 7.1 - pessoas.blade.php
```php=
<h2>Listagem de Pessoas</h2>
<p/>
<!--tem sessao se tiver imprime-->
@if(session('success'))
<div>
  {{session('success')}}
</div>
@endif
<table border="1">
  <tr>
    <td>Id</td>
    <td>Nome</td>
    <td>Endereco</td>
    <td>Idade</td>
    <td>Detalhar</td>
  </tr>
  @foreach ($pessoas as $p)
  <tr>
    <td>{{$p->id}}</td>
    <td>{{$p->nome}}</td>
    <td>{{$p->endereco}}</td>
    <td>{{$p->idade}}</td>
    <td><a href="{{route('buscar',$p->id)}}">find</a></td>
  </tr>
  @endforeach
</table>
<br/>
<a href="{{route('formulario')}}">Cadastrar Pessoa</a>
```
----

### 7.2 - cadastrar.blade.php
```php=
<!doctype html>
<html lang="pt">
<head>
</head>
<body>
  <form method="post" action="{{route('salvarPessoa')}}">
    @csrf
    <br/>Nome<br/>
    <input type="text" name="nome" id="nome" 
    required="required"  />
    <br/>Idade<br/>
    <input type="number" name="idade" id="idade" required="required" value="{{old('idade')}}"   />
    @if ($errors->has('idade'))
    {{$errors->first('idade')}}
    @endif  
    <br/>Endereco<br/>
    <input type="text" name="endereco" id="endereco" required="required"  />
    <br/>
    <button type="submit">Enviar os Dados</button>
  </form>
  <br/>
  <a href="{{route('listar')}}">Listar Pessoas</a>
</body>
</html>

```
----

### 7.3 - buscapessoa.blade.php
```php=
<h2>Detalhes da Pessoa</h2>
<hr/>
Id :{{$pessoa->id}}<br/>
Nome :{{$pessoa->nome}}<br/>
Endereco :{{$pessoa->endereco}}<br/>
Idade :{{$pessoa->idade}}<br/>
<br/>
<a href="{{route('listar')}}">Voltar Listagem</a>
```
----

## 8 - Rodar o projeto..
`php artisan serve --port=8888`
Digitar a URL passada...
http://127.0.0.1:8888/




Criar controller e model...

`php artisan make:controller NameController --resource --model=NameModel`



---
---

# Dia 02

## Criado Model clientes
==php artisan make:model Model/Clientes==

```php=
<?php

namespace App\Model;

use Illuminate\Database\Eloquent\Model;

class Cliente extends Model
{
    protected $primaryKey = "id";
    
    protected $fillable = [
        "nome", "email", "sexo", "idade"
    ];

    protected $table = "clientes";
}
```


## Criando Migration clientes
==php artisan make:migration clientes==
```php=
<?php

use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;

class Clientes extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('clientes', function (Blueprint $table) {

            $table->Increments('id');
            $table->string('nome',50);
            $table->string('email',100)->unique();
            $table->enum('sexo', ['m', 'f']);	
            $table->integer('idade');
            $table->timestamps();
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('clientes');
        
    }
}

```
==php artisan migrate==


[Campos permitidos para mirations](https://laravel.com/docs/5.8/migrations#columns)

## Se precisar alterar o banco de dados
Usa o mesmo arquivo *migrate* e cria a estrutura no novo banco de dados informado no arquivo **/.env**.
:::danger
:warning: Limpa os dados (Cuidado!!!)

==php artisan migrate:refresh==

:warning: Apaga a tabela (Cuidado!!!)
==php artisan migrate:refresh --seed==
:::


## Seeder

Procedimento teste para popular com dados randomicos nossa tabela...

==php artisan make:seeder ClientesTableSeeder==

```php=
<?php

use Illuminate\Database\Seeder;

use Illuminate\Support\Str;
use Illuminate\Support\Facades\DB;

class ClientesTableSeeder extends Seeder
{
    /**
     * Run the database seeds.
     *
     * @return void
     */
    public function run()
    {
        DB::table('clientes')->insert([
            'nome' => Str::random(10),
            'email' => Str::random(10).'@gmail.com',
            'sexo' => 'm',
            'idade' => '10'
        ]);
    }
}
```

==php artisan db:seed --class ClientesTableSeeder==

---

## Exemplo de migration para ajuste de posicao de campo

==php artisan make:migration add_idade_table_clientes  --table=clientes==
 

```php=
<?php

use IlluminateSupportFacadesSchema;
use IlluminateDatabaseSchemaBlueprint;
use IlluminateDatabaseMigrationsMigration;

class AddIdadeTableClientes extends Migration
{
    
    public function up()
    {
        Schema::table('clientes', function (Blueprint $table) {
             $table->integer('idade')->after('email');
        });
    }

    public function down()
    {
       
    }
}
```

==php artisan migrate==

---

## Criando controller ClienteController

==php artisan make:controller ClienteController==


---

## Implementando Bootstrap no Lara

```bash=
composer require laravel/ui
php artisan ui bootstrap
npm install && npm run dev
```

---


composer require laravel/ui &&
php artisan ui bootstrap --auth&&
npm install && npm run dev 


## Inclusao de idiomas...

Baixar repo e incluir em ==resources/lang==
https://github.com/caouecs/Laravel-lang

ajustar locale dentro do "/config/app.php"

---
---

## Relacionamento Um pra Um...

```bash=
 php artisan make:model Model/Endereco
 php artisan make:model Model/Funcionario
```

```php=
<?php

namespace App\Model;

use Illuminate\Database\Eloquent\Model;

class Funcionario extends Model
{
    protected $primaryKey = "id";
    
    protected $fillable = [
        'id', 
        'nome', 
        'email'
    ];
    
    protected $tables = "funcionarios";

    public function endereco()
    {
        return $this->hasOne(Endereco::class, 'funcionario_id', 'id');
    }
}

```

```php=
<?php

namespace App\Model;

use Illuminate\Database\Eloquent\Model;

class Endereco extends Model
{
    protected $primaryKey = "funcionario_id";

    protected $fillable = [
        'funcionario_id', 
        'logradouro', 
        'bairro',
        'cidade', 
        'estado',
        'cep'
    ];
    
    protected $tables = "enderecos";

    public function funcionario()
    {
        return $this->belongsTo(Funcionario::class, 'funcionario_id', 'id');
    }
}

```

```bash=
php artisan make:migration funcionarios
php artisan make:migration enderecos
```
---
```php
<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

class Funcionarios extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {

        Schema::create('funcionarios', function (Blueprint $table) {
            $table->bigIncrements('id');
            $table->string('nome', 50);
            $table->string('email',50)->unique();
            $table->timestamps();
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('funcionarios');
        
    }
}

```

---

==php artisan make:controll FuncionarioController --resource==    

# Exemplo do Controller

Ver o método findFuncionario onde aplicamos filtros tanto na tabela principal (funcionarios) a secundária 


```php
<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use App\Model\Funcionario;
use App\Model\Endereco;
use DB;

class FuncionarioController extends Controller
{
    protected $funcionarios;

    public function __construct(Funcionario $funcionarios)
    {
        $this->funcionarios = $funcionarios;
    }

    /**
     * Display a listing of the resource.
     *
     * @return \Illuminate\Http\Response
     */
    public function index(Request $req)
    {
        $lista = $this->funcionarios->all();
        //dd($lista);
        if ($req->session()->has('message')===false) {
            $req->session()->put("message", "Bem vindo");
        }
        return view('index', [ "funcionarios" => $lista ]);
    }

    /**
     * Show the form for creating a new resource.
     *
     * @return \Illuminate\Http\Response
     */
    //Não esquecer do @csrf
    public function createFuncionario()
    {
        return view('createFuncionario');
    }

    /**
     * Store a newly created resource in storage.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return \Illuminate\Http\Response
     */
    public function store(Request $request)
    {
        //dd($request);
        $ende=null;
        $message=null;
        $request->validate([    
            'nome'=>'required|string|max:50|min:2',
            'email'=>'email',
            'cep'=>'required|string|min:8|max:10',
            'logradouro'=>'required',
            'bairro'=>'required',
            'cidade'=>'required',
            'estado'=>'required|string|max:2|min:2',
        ]);

        try { 
            DB::beginTransaction();
            $funcionario = Funcionario::create([
                'nome' => $request->get('nome'),
                'email' => $request->get('email')
            ]);
            if ($funcionario) {
                $ende=$funcionario->endereco()->create([
                    //'funcionario_id' => $funcionario->attributes['id'],
                    'logradouro' => $request->get('logradouro'),
                    'bairro' => $request->get('bairro'),
                    'cidade' => $request->get('cidade'),
                    'estado' => $request->get('estado'),
                    'cep' => $request->get('cep')
                ]);
            }
            if ($funcionario && $ende) {
                DB::commit();
                $message='Funcionário cadastrado com sucesso';
            } else {
                DB::rollBack();
                $message='Erro ao cadastrar funcionário';
            }
            return redirect()->route('index')->
                with('message', $message);
        } catch(\Exception $ex) {
            return redirect()->route('formulario')->
                with('message', 'Erro ao criar funcionário: '.$ex->getMessage());
        }

    }

    public function erros(Reques $ex) {
        return view('erros');
    }



    /**
     * Display the specified resource.
     *
     * @param  int  $id
     * @return \Illuminate\Http\Response
     */
    public function findFuncionario(Request $request)
    {
        $request->session()->forget('message');

        //dd(Endereco::where('logradouro', '=', 'Rua a')->get() );
        $query=
        $funcs = $this->funcionarios->where('nome', '=', $request->get('buscar'))
                                    ->orWhere('email', '=', $request->get('buscar'))
                                    ->orWhere('id', '=', $request->get('buscar'))
                                    ->orWhereHas('Endereco', function ($query) use ($request) {
                                        //dd($request);
                                        $query->where('logradouro', '=', $request->get('buscar'));
                                    })->get();
        /*
        $funcs = DB::select('select * from funcionarios 
        where nome = ? OR email = ? OR id = ? ', [
                                    $request->get('buscar'), 
                                    $request->get('buscar'),
                                    $request->get('buscar')]);
        */

        $message='';
        if (count($funcs)==0) {
            $message="Não foram encontrados funcionarios para a consulta: "
            .$request->get('buscar');
            $request->session()->put("message", $message);
        }


        return view('index',  [ "funcionarios" => $funcs ])->
            with('message', $message);
    }

    /**
     * Display the specified resource.
     *
     * @param  int  $id
     * @return \Illuminate\Http\Response
     */
    public function show($id)
    {
        //
    }

    /**
     * Show the form for editing the specified resource.
     *
     * @param  int  $id
     * @return \Illuminate\Http\Response
     */
    public function edit($id)
    {
        //
    }

    /**
     * Update the specified resource in storage.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  int  $id
     * @return \Illuminate\Http\Response
     */
    public function update(Request $request, $id)
    {
        //
    }

    /**
     * Remove the specified resource from storage.
     *
     * @param  int  $id
     * @return \Illuminate\Http\Response
     */
    public function destroy($id)
    {
        //
    }
}

```

# Dia 06

## 1 para muitos - Relacionamentos - hasMany
### Projeto Correntista - Laravel

Neste estudo não vamos usar o diretório ==/app/Model== para as nossas classes modelo.
Vamos criar seguindo o novo padrão do Laravel que é deixá-las no diretório ==/app==

:::info
A regra é:
 - Em casos de poucas models, podemos deixar no local default (==/app==);
 - para projetos maiores, a fim de uma melhor organização, utilizar a pasta Model(==/app/Model==).
:::

Inicialmente teremos duas tabelas, "correntista" e "movimentacoes".

A tabela correntista terá realcionamento de um para muitos com a tabela movimentacoes.


```graphviz
digraph G {
size="5,5"
node[shape=record,style=filled,fillcolor=gray95]
edge[dir=back, arrowtail=empty]

1[label = "{Correntista|- id\n- nome\n- saldo\n}"]
2[label = "{Movimentacoes|-id\n- operacao\n- valor}"]

1->2 }
```


Seguem os arquivo migrations:

**2019_09_16_122315_create_correntistas_table.php**
```php=
<?php

use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;

class CreateCorrentistasTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('correntistas', function (Blueprint $table) {
            $table->increments('id');
            $table->string('nome', 50);
            $table->decimal('saldo', 8 ,2);
            $table->timestamps();
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('correntistas');
    }
}


```

**2019_09_16_122326_create_movimentacoes_table**
```php=
<?php

use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;

class CreateMovimentacoesTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('movimentacoes', function (Blueprint $table) {
            $table->increments('id');
            $table->string('operacao', 20);
            $table->double('valor');
            $table->integer('correntista_id')->unisigned();
            $table->foreign('correntista_id')->references('id')->on('correntistas');
            $table->timestamps();
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('movimentacoes');
    }
}

```

Para cada tabela temos um arquivo de classe (modelo). Segue abaixo:

**Correntista.php**
```php=
<?php

namespace App;

use Illuminate\Database\Eloquent\Model;
use App\Movimentacao;

class Correntista extends Model
{
    protected $primaryKey = "id";

    protected $fillable = ['id', 'nome', 'saldo'];

    protected $table = 'correntistas';

    public function movimentacoes()
    {
        return $this->hasMany(Movimentacao::class);
    }
}
```

**Movimentacao.php**
```php=
<?php

namespace App;

use Illuminate\Database\Eloquent\Model;
use App\Correntista;

class Movimentacao extends Model
{
    //Many to One
    protected $primaryKey = "id";

    protected $fillable = ['id', 'operacao', 'valor', 'correntista_id'];

    protected $table = 'movimentacoes';
    
    //Muitos para um singular (chamando a classe com hasMany)
    public function correntista()
    {
        return $this->belongsTo(Correntista::class);
    }


}

```
## Criando o controller
php artisan make:controller correntistaController

```php=
<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use App\Correntista;
use App\Movimentacao;
use DB;

class CorrentistaController extends Controller
{
    protected $correntistas;

    public function __construct(Correntista $correntistas)
    {
        $this->correntistas = $correntistas;
    }

    /**
     * Display a listing of the resource.
     *
     * @return \Illuminate\Http\Response
     */
    public function index(Request $req)
    {
        $lista = $this->correntistas->all();
        //dd($lista);
        if ($req->session()->has('message')===false) {
            $req->session()->put("message", "Bem vindo");
        }
        return view('index', [ "correntistas" => $lista ]);
    }

    /**
     * Display a listing of the resource.
     *
     * @return \Illuminate\Http\Response
     */
    public function rest(Request $req)
    {
        //$lista = $this->correntistas->all();
        //dd($lista);
        //return json_encode($lista);
        return response()->json(Correntista::all(), 200);
    }


    public function cadastro()
    {
        return view('cadastro');
        //return view('cadastrar', compact('cliente'));
    }

    public function create(Request $req)
    {
        $req->validate([
            'nome'=>'required|string|max:50|min:2',
            'saldo'=>'required|numeric'
        ]);
        //dd($req->id);
        /* Meu código */
        $correntista = $req->all();
        $this->correntistas->create($correntista);

        return redirect()->route('index')->
            with('message', 'Correntista cadastrado com sucesso');

    }


    public function deposito($id)
    {
        $correntista = $this->correntistas->find($id);
        return view('deposito', compact('correntista'));
    }


    public function retirada($id)
    {
        $correntista = $this->correntistas->find($id);
        return view('retirada', compact('correntista'));
    }

    public function depositopost(Request $req)
    {
        $movimentacao=null;
        $message=null;
        $req->validate([    
            'id'=>'required|numeric',
            'nome'=>'required|string|max:50|min:2',
            'valor'=>'required|numeric|min:1'
        ]);

        try { 
            DB::beginTransaction();
            
            $correntista = $this->correntistas->findOrFail($req->get('id'));

            $movimentacao = Movimentacao::create([
                'operacao' => 'deposito',
                'valor' => $req->get('valor'),
                'correntista_id' => $req->get('id')
            ]);
            if ($movimentacao) {
                $novoSaldo=($correntista->saldo + $req->get('valor'));
                //dd($params['id']);
                
                $correntista->update(['saldo' => $novoSaldo]);
                //OU
                //$correntista = $this->correntistas->findOrFail($req->get('id'));
                //deposito=$req->valor;
                //$correntista->saldo = $correntista->saldo + deposito;
                //$correntista->save();
                

            }
            if ($movimentacao && $correntista) {
                DB::commit();
                $message='Depósito realizado com sucesso.';
            } else {
                DB::rollBack();
                $message='Falha ao registrar depósito.';
            }
            return redirect()->route('index')->
                with('message', $message);
        } catch(\Exception $ex) {
            return redirect()->route('formulario')->
                with('message', 'Falha ao registrar depósito: '.$ex->getMessage());
        }

    }

    public function retiradapost(Request $req)
    {
        $movimentacao=null;
        $message=null;
        $req->validate([    
            'id'=>'required|numeric',
            'nome'=>'required|string|max:50|min:2',
            'valor'=>'required|numeric'
        ]);

        try { 
            DB::beginTransaction();
            
            $correntista = $this->correntistas->findOrFail($req->get('id'));

            $movimentacao = Movimentacao::create([
                'operacao' => 'retirada',
                'valor' => $req->get('valor'),
                'correntista_id' => $req->get('id')
            ]);
            if ($movimentacao) {
                $novoSaldo=($correntista->saldo - $req->get('valor'));
                //dd($params['id']);
                
                $correntista->update(['saldo' => $novoSaldo]);
                //OU
                //$correntista = $this->correntistas->findOrFail($req->get('id'));
                //deposito=$req->valor;
                //$correntista->saldo = $correntista->saldo + deposito;
                //$correntista->save();
                

            }
            if ($movimentacao && $correntista) {
                DB::commit();
                $message='Depósito realizado com sucesso.';
            } else {
                DB::rollBack();
                $message='Falha ao registrar depósito.';
            }
            return redirect()->route('index')->
                with('message', $message);
        } catch(\Exception $ex) {
            return redirect()->route('formulario')->
                with('message', 'Falha ao registrar depósito: '.$ex->getMessage());
        }
    }
}
```

# Muitos para muitos - Relacionamentos - many2Many

Neste projetos usaremos a estrutura de **alunos** e **cursos** onde o relacionamento entre ambos é de muitos para muitos.

```graphviz
digraph G {
size="5,5"
node[shape=record,style=filled,fillcolor=gray95]
edge[dir=back, arrowtail=empty]

1[label = "{Alunos|- id\n- nome\n- email\n}"]
2[label = "{Aluno_Curso|-id\n- aluno_id\n- curso_id}"]
3[label = "{Cursos|-id\n- descrição}"]

1->2
2->1
2->3
3->2}
```

---

# DIA 7

## JWT (Json Web Token)

### Referências
[https://jwt.io/](https://jwt.io/)

fluxo padrao:
![](https://i.imgur.com/sOvUlUb.png)


É um padrão de autenticação que utiliza token
Sistema de proteção.

Bearer - padrão de autenticação simples - necessita de um token

Rota livre - onde se pode fazer o que quiser

Rota segura - só entra autenticado

### Início
```bash=

php artisan make:model Model/Aluno

php artisan make:migration alunos

php artisan make:controller AlunoController

```
Editar o arquivo .env com os dados do exemplo.

/.env
```bash=9
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=BDOICOTIREST
DB_USERNAME=root
DB_PASSWORD=coti
```

App/Model/Aluno.php
```php=
<?php

namespace App\Model;

use Illuminate\Database\Eloquent\Model;

class Aluno extends Model
{
    protected $table = 'alunos';

    protected $primaryKey = 'id';
    
    protected $fillable = [
        'id',
        'nome',
        'email',
        'password',
    ];
}

```
### Instalar JWT no Laravel
```bash=

composer require tymon/jwt-auth:1.0.*

php artisan vendor:publish --provider="TymonJWTAuthProvidersLaravelServiceProvider"

php artisan jwt:secret
```

### Exemplo de implementação de RateLimit, sendo para esta rota 5 chamadas/minuto autorizado
Route::get('/lista','AlunoController@listar')->middleware('throttle:5,1')->name('listagem');


# Exemplo 7
## Chamadas Rest

Pessoa.php
```php=
<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Pessoa extends Model
{
    protected $table = 'pessoas';

    protected $primaryKey = 'id';

    protected $fillable = [
        'nome',
        'email',
        'idade',
    ];
    
}

```


web.php
```php=
<?php

Route::prefix('pessoa')
    ->middleware('throttle:5,1')
    ->group(function () {

        Route::get('/', 'PessoaController@index')->name('index');
        Route::get('/{id}', 'PessoaController@findById')->name('find');

        Route::post('/', 'PessoaController@store')->name('store');

        Route::put('/', 'PessoaController@update')->name('update');

        Route::delete('/{id}', 'PessoaController@delete')->name('delete');

    });

```

---

PessoaController.php
```php=
<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use App\Pessoa;

class PessoaController extends Controller
{
    protected $pessoas;
    
    public function __construct(Pessoa $pessoas)
    {
        $this->pessoas = $pessoas;
    }
    
    public function index()
    {
        return response()->json(['lista' => Pessoa::all() ],200 );
    }
    
    
    public function store(Request $req)
    {
        $pessoa = new Pessoa($req->all());
        $pessoa->save();  
        return response()->json(['msg'=>'Store OK','pessoas' => Pessoa::all()]); 
    }
    
    
    public function delete($id)
    {
        $pessoa = Pessoa::find($id);
        $pessoa->delete();  
        return response()->json(['msg'=>'Delete OK','pessoas' => Pessoa::all()]); 
    }
    
    
    public function update(Request $req)
    {
        $pessoa = Pessoa::find($req->input('id'));
        $pessoa->fill($req->all());
        $pessoa->save();  
        return response()->json(['msg'=>'Update OK','pessoas' => Pessoa::all()]); 
    }
    
    public function findById($id)
    {
        return response()->json(['pessoa', Pessoa::find($id)], 200);
    }
    
}

```

---

migration_pessoas.php
```php=
<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

class Pessoas extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('pessoas', function (Blueprint $table) {
            $table->bigIncrements('id');
            $table->string('nome');
            $table->string('email')->unique();
            $table->integer('idade');
            $table->timestamps();
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('pessoas');
    }
}
```

---
---


# Email Mail
[http://dontpad.com/emailmail](http://dontpad.com/emailmail)

---
---

# Projeto Final

```graphviz
digraph G {
size="5,5"
node[shape=record,style=filled,fillcolor=gray95]
edge[dir=back, arrowtail=empty]


1[label = "{Artigo|-id\n- titulo\n- conteudo\n|escritor()}"]

2[label = "{Escritor|- id\n- nome\n- email\n- foto\n|artigos()}"]

3[label = "{ControllerEscritor|+index()\n+ create()\n+ update()\n+ delete()\n}"]

1->2}
```
---
---

## Criando os modelos 
php artisan make:model Escritor
php artisan make:model Artigo

## Criando as "migrations" para os Banco de dados
php artisan make:migration escritores
php artisan make:migration artigos

## Criando a Controller
php artisan make:controller ControllerEscritor --resource

## Criando a base de dados (MySQL)
```bash=
mysql -u root -p
mysql> create database COTIOIFINAL;
Query OK, 1 row affected (0,02 sec)

mysql> use COTIOIFINAL
Database changed
mysql>
```

.env
```bash
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=COTIOIFINAL
DB_USERNAME=root
DB_PASSWORD=coti
```
# Arquivos modelos gerados
## Escritor.php
```php=
<?php

namespace App;

use Illuminate\Database\Eloquent\Model;
use App\Artigo;

class Escritor extends Model
{
    protected $primaryKey = "id";

    protected $fillable = [
        'id', 
        'nome', 
        'email', 
        'foto'
    ];

    protected $table = 'escritores';

    public function artigos()
    {
        return $this->hasMany(Artigo::class);
    }
}

```

## Artigos.php
```php=
<?php

namespace App;

use Illuminate\Database\Eloquent\Model;
use App\Escritor;

class Artigo extends Model
{
    //Many to One
    protected $primaryKey = "id";

    protected $fillable = [
        'id', 
        'titulo', 
        'conteudo', 
        'escritor_id'
    ];

    protected $table = 'artigos';
    
    //Muitos para um singular (chamando a classe com hasMany)
    public function escritor()
    {
        return $this->belongsTo(Escritor::class);
    }
}
```

# Arquivos gerados para migration

## 2019_09_18_140150_escritores.php
```php=
<?php

use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;

class Escritores extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('escritores', function (Blueprint $table) {
            $table->increments('id');
            $table->string('nome', 50);
            $table->string('email', 50)->unique();
            $table->string('foto', 255);
            $table->timestamps();
        });
    }


    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('escritores');
    }
}

```

## 2019_09_18_140155_artigos.php
```php=
<?php

use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;

class Artigos extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('artigos', function (Blueprint $table) {
            $table->increments('id');
            $table->string('titulo', 50);
            $table->longText('conteudo');
            $table->integer('escritor_id')->unsigned();
            $table->foreign('escritor_id')->references('id')->on('escritores');
            $table->timestamps();
        });
    }


    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('artigos');
    }
}

```
## Adicionar excessao de csrf em App\Http\Middleware\VerifyCsrfToken.php
Temos que adicionar esta exceção para que seja possível realizar o post via REST.
Para o curso colocamos tudo liberado '*'.
```php=22
    protected $except = [
        '*'
    ];
```


# Arquivo controller: ControllerEscritor.php
```php=
<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use App\Escritor;
use App\Artigo;
use DB;

class ControllerEscritor extends Controller
{
    protected $escritores;

    public function __construct(Escritor $escritores)
    {
        $this->escritores = $escritores;
    }

    /**
     * Display a listing of the resource.
     *
     * @return \Illuminate\Http\Response
     */
    public function index()
    {
        //Vamos exibir a listagem em JSON

        return response()->json(
            [
                'lista' => $this->escritores->all(),
                'message' => 'Dados retornados com sucesso'
            ], 200
        );
    }

    /**
     * Show the form for creating a new resource.
     *
     * @return \Illuminate\Http\Response
     */
    public function create()
    {
        //
    }

    /**
     * Store a newly created resource in storage.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return \Illuminate\Http\Response
     */
    public function store(Request $request)
    {
        DB::beginTransaction();
        try{
            //Vamos verificar se o escritor já existe
            $escritor = $this->escritores
                            ->where('email', $request->email)
                            ->first();
            
            if (!isset($escritor)) {
                $escritor = new Escritor();
                //Solução do Woney usa o método fill ($escritor->fill($request->all()));
                $escritor->nome =  $request->input("nome");
                $escritor->email = $request->input("email");
                $escritor->foto = $request->input("foto");
                $escritor->save();
            }
            //return response()->json(['message' => $escritor], 200);
            $artigo = new Artigo();
            //Solução do Woney usa o método fill ($escritor->fill($request->all()));
            $artigo->titulo = $request->input("titulo");
            $artigo->conteudo = $request->input("conteudo");
            $escritor->artigos()->save($artigo);
            DB::commit();
            return response()->json(['message' => 'Dados gravados'], 200);
        } catch (\Exception $e) {
            DB::rollback();
            return response()->json(
                ['message' => 'Erro ao gravar os dados: '.$e->getMessage()]
                , 200
            );
        }
    }

    /**
     * Display the specified resource.
     *
     * @param  int  $id
     * @return \Illuminate\Http\Response
     */
    public function show($id)
    {
        //
    }

    /**
     * Show the form for editing the specified resource.
     *
     * @param  int  $id
     * @return \Illuminate\Http\Response
     */
    public function edit($id)
    {
        //
    }

    /**
     * Update the specified resource in storage.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  int  $id
     * @return \Illuminate\Http\Response
     */
    public function update(Request $request)
    {
        $escritor = $this->escritores->find($request->input('id'));
        if (isset($escritor)) {
            $escritor->fill($request->all());
            $escritor->save();
            $message='Dados atualizados';
        } else {
            $message = 'Registro não encontrado';
        }
        return response()->json(['message' => $message], 200);
    }

    /**
     * Remove the specified resource from storage.
     *
     * @param  int  $id
     * @return \Illuminate\Http\Response
     */
    public function delete($id)
    {
        $escritor = $this->escritores->find($id);
        if (isset($escritor)) {
            $escritor->delete();
            $message = 'Dados apagados';
        } else {
            $message = 'Registro não encontrado';
        }
        return response()->json(['message' => $message], 200);
    }
}

```

# Arquivo de rotas "web.php"
```php=
<?php

Route::prefix('api')
->middleware('throttle:5,1')
->group(function () {

    Route::get('/', 'ControllerEscritor@index')->name('escritor.lista');
    
    Route::get('/{id}', 'ControllerEscritor@show')->name('escritor.show');
    
    Route::post('/', 'ControllerEscritor@store')->name('escritor.create');
    
    Route::put('/', 'ControllerEscritor@update')->name('escritor.update');
    
    Route::delete('/', 'ControllerEscritor@delete')->name('escritor.delete');
    
});

```

### Exemplos de relacionamentos Laravel.
```php=
// Relacionamento 1 para 1
class Usuario extends Eloquent {
    public function conta()
    {
        return $this->hasOne('Conta');
    }
}
class Conta extends Eloquent {
    public function usuario()
    {
        return $this->belongsTo('Usuario');
    }
}
 
// Relacionamento 1 para N
class Estado extends Eloquent {
    public function cidades()
    {
        return $this->hasMany('Cidade');
    }
}
class Cidade extends Eloquent {
    public function estado()
    {
        return $this->belongsTo('Estado');
    }
}
 
// Relacionamento N para N
class Pessoa extends Eloquent {
    public function cidades()
    {
        return $this->belongsToMany('Cidade');
    }
}
class Cidade extends Eloquent {
    public function pessoas()
    {
        return $this->belongsToMany('Pessoa');
    }
}
```





