Tabela de conteúdos

Laravel

Laravel é um Framework PHP para desenvolvimento de soluções Web (https://laravel.com/).

Instalação

Atualmente a InfoTIC trabalha com as versões 5.4, 5.5 e 5.6 do framework, os requisitos do servidor para essas versões são, respectivamente:

5.4 5.5 5.6
PHP >= 5.6.4 PHP >= 7.0.0 PHP >= 7.1.3
Extensão PHP OpenSSL Extensão PHP OpenSSL Extensão PHP OpenSSL
Extensão PHP PDO Extensão PHP PDO Extensão PHP PDO
Extensão PHP Mbstring Extensão PHP Mbstring Extensão PHP Mbstring
Extensão PHP Tokenizer Extensão PHP Tokenizer Extensão PHP Tokenizer
Extensão PHP XML Extensão PHP XML Extensão PHP XML
Extensão PHP Ctype
Extensão PHP JSON

LaravelExtension

Introdução

O presente tutorial serve para facilitar a construção de projetos em PHP usando o framework Laravel. Assume-se que o sistema operacional é o Ubuntu 14.04 ou superior (o que pode ser visto em System Settings → Details) e que a versão de PHP é pelo menos a 5.6 (usando o comando php -v). É possível instalar o Laravel no Windows. Este tutorial foi executado no Windows 8.1 com sucesso. A IDE usada para a elaboração deste tutorial é o NetBeans 8.1. Este tutorial foi feito usando o Laravel 5.2. Na medida do possível, será atualizado quando novas versões forem disponibilizadas.

Composer

Primeiramente deve-se instalar o Composer, para que se possa instalar os pacotes que o projeto usará sem ser necessário comitar no repositório os arquivos de código-fonte desses pacotes. Para isso, deve-se acessar https://getcomposer.org/ e seguir as instruções de como instalar o Composer, que serão alguns comandos que devem ser copiados e colados no terminal. Os comandos de instalação mudam de versão para versão e, portanto, ao instalar o Composer, deve-se ir ao site para ver quais comandos usar para instalar uma versão de Composer do zero.

Para facilitar seu uso, deve-se criar um alias para ele. Senão, será necessário digitar algo como no Ubuntu:

php /home/<nome_do_usuario>/composer.phar 

sempre que for usá-lo. Para isso, acessando como root (usando o comando sudo su), digite:

mv composer.phar /usr/local/bin/composer

Já no Windows, ao invés de ter que digitar algo como:

C:\ProgramData\ComposerSetup\bin\composer

apenas vá em Painel de Controle → Sistema → Configurações Avançadas de Sistema → Variáveis de Ambiente e se a pasta C:\ProgramData\ComposerSetup\bin não estiver na variável PATH, adicione-a. Saia dando OK e reinicie o terminal para pegar o caminho atualizado.

Agora é possível usar o Composer usando o comando composer de qualquer lugar.

Se o Composer reclamar que ele está antigo e pedir para se atualizar, apenas use o comando:

composer self-update

Laravel Homestead / Máquina Virtual

Framework Laravel tem alguns requisitos de sistema, esses requisitos são satisfeitos pela máquina virtual Laravel Homestead, que pode ser usada para como um ambiente local de desenvolvimento.

IDEs

NetBeans

Instalação e Configuração do Projeto no NetBeans

Rodando o Projeto no NetBeans

Usando o Laravel

Instalando o Laravel e Criando um Novo Projeto

Para instalar o Laravel, faça:

composer global require "laravel/installer"

Certifique-se de que a pasta ../Composer/vendor/bin esteja no path de seu sistema.

Se estiver no Windows, vá em Painel de Controle → Sistema → Configurações Avançadas de Sistema → Variáveis de Ambiente e a pasta não estiver na variável PATH, adicione-a. Ela deve estar em uma pasta similar a C:\Users\<nome_de_usuario>\AppData\Roaming\Composer\vendor\bin. Saia dando OK e reinicie o terminal para pegar o caminho atualizado.

Se estiver no Ubuntu, coloque a seguinte linha ao final de /etc/bash.bashrc em modo sudo:

export PATH=/home/<nome_usuario>/.composer/vendor/bin:$PATH

Para se criar um novo projeto usando Laravel, execute na pasta onde deseja colocar o projeto:

laravel new <nome_projeto>

Caso não queira instalar o Laravel globalmente ou tenha algum problema em sua instalação, principalmente no Windows, crie um novo projeto diretamente usando o composer:

composer create-project laravel/laravel <nome_projeto>

Se tiver faltando alguma extensão do PHP, no Windows é só descomentar o uso da DDL referente à extensão desejada no Windows e reiniciar o terminal. Já no Ubuntu é necessário instalar a extensão necessária com o comando:

sudo apt-get install <nome_da_extensão>

Antes de tentar criar o projeto novamente, apague a pasta do projeto.

Criando e Configurando um Banco de Dados

Depois de fazer o projeto lógico de seu banco, crie apenas a base de dados (sem as tabelas) localmente no gerenciador de banco de dados (SGBD) escolhido. Depois, no .env, coloque as configurações de seu banco, preenchendo DB_HOST, DB_CONNECTION, DB_DATABASE, DB_USERNAME e DB_PASSWORD. Em config/database.php, caso a configuração do SGBD escolhido não esteja presente, adicione-a pelo Composer, lembrando-se de que tem que adicionar o Service Provider em config/app.php. Lembre-se de que precisa tanto ter o SGBD quanto seu driver para PHP instalados. Dependendo do SGBD, pode ser necessário adicionar alguma variável de ambiente ao .env.

Em geral, não será necessário instalar a configuração de um SGBD adicional, já que o Laravel vem com PostgreSQL, MySQL, SQLite e SQLServer. O acesso ao SQLServer é que é mais complicado, pois é preciso instalar no PHP umas bibliotecas adicionais. Com as devidas bibliotecas instaladas, o acesso ao SQLServer poderá ser feito de maneira transparente pelo Laravel, da mesma forma que se acessa os outros bancos. Basicamente, é necessário ter o pdo_dblib com o freetds habilitado. Isso em Ubuntu e CentOS. Para outros SOs, pode ser que sejam necessárias mais ou menos bibliotecas adicionais.

Migrations

Agora é hora de criar as tabelas propriamente ditas. Se estiver apenas em ambiente de desenvolvimento ainda, sem dados em produção, crie uma migration para cada tabela. Uma migration é um script para o banco de dados que deve ser rodado sempre que for alterado. Ele facilita o desenvolvimento em grupo e a implantação da aplicação, uma vez que é só rodar o script. Em desenvolvimento, se precisar alterar uma tabela, apague e recrie a base no SGBD, altere a migration dela e mande rodar os scripts que elas serão criadas novamente. Já se estiver em produção com dados que não possam ser perdidos, é preciso criar uma migration de alteração e executá-la para não perder dados.

Para criar uma migration de criação de tabela, execute o seguinte comando no diretório da aplicação:

php artisan make:migration create_<table_name>_table --create="<table_name>"

Crie primeiramente as migrations para as tabelas sem chave estrangeira e depois adicione as que referenciam as já criadas. Senão, ao rodar os scripts (que são executados todos juntos), vai dar erro dizendo que a tabela referenciada não existe, já que os scripts das migrations são executados na ordem em que foram criados.

Agora deve-se editar o método up() da migration, que cria vai criar tabela ao ser executado, colocando cada coluna da tabela, suas restrições, indicar as chaves estrangeiras, etc.

Em geral a coluna id que já vem com a migration na primeira linha da criação da tabela será a chave primária. Caso outra coluna seja a chave primária e não seja necessário o id, é só removê-la e adicionar as colunas que serão a chave primária fazendo algo como:

$table->primary([<nome_coluna_1, …, nome_coluna_n]);

Se a chave for de apenas uma coluna, não é preciso passar um vetor de uma unidade; apenas passe o nome da coluna como parâmetro. Lembre-se de declarar a coluna, como mostrado abaixo, antes de colocá-la em uma chave ou índice.

Para declarar cada coluna, faça algo como:

$table→<tipo_coluna>('<nome_da_coluna>', ...)-><modificador>();

Os tipos da coluna justamente com os parâmetros extras, que em geral são limites de tamanho, podem ser vistos em https://laravel.com/docs/5.2/migrations#creating-columns

Após declarar a coluna, é possível declarar um ou mais modificadores para ela. Basta chamar um método ou mais métodos um após o outro com os modificadores necessários. Os modificadores são:

Para criar um índice, adicione à migration algo como:

$table→index([<nome_coluna_1, …, nome_coluna_n], nome_do_indice);

Onde o nome do índice é opcional e as colunas passadas no primeiro campo são as colunas que formam o índice. Se o índice for de apenas uma coluna, não é preciso passar um vetor de uma unidade; apenas passe o nome da coluna no primeiro parâmetro. Alternativamente, ao criar a coluna, adicione o modificador index() ao seu final.

Para criar uma chave estrangeira referenciando outra tabela, faça algo como:

$table->foreign('id_<nome_tabela>')->references('id')->on('<nome_tabela>');

supondo que a chave primária de <nome_tabela> seja id, que é o caso mais comum.

Caso na declaração da chave estrangeira precise dizer o que fazer com a linha em caso de remoção ou alteração, após o método on(), chame o onDelete('<ação>') ou onUpdate('<ação>'), respectivamente.

Em alguns sistemas há tabelas que precisam ter dados desde quando o sistema é posto em produção. Neste caso, as migrations devem ter inserções no método up() após a criação da tabela. Exemplos são credenciais de administrador padrão para o acesso inicial a um sistema ou tabelas de tipo. Para fazer isso, use um código similar ao abaixo:

DB::table('<nome_tabela>')->insert(
   array(
           '<coluna_1>' => '<valor_1>',
           ...
           '<coluna_n>' => '<valor_n>'
        )
;

Para executar as migrations, execute o seguinte comando:

php artisan migrate

Se o comando for executado com sucesso, suas tabelas serão criadas na base de dados, com algumas tabelas adicionais das migrations que veem com o Laravel e com a tabela migrations.

Models

<p style=“color: red; font-weight: bold;”> Quem construiu esse doc, rever essa parte pfvr, considerando o comentário: “De acordo com a documentação (https://laravel.com/docs/8.x/eloquent#local-scopes), o melhor seria ter scope method para esses casos.” </p>

Após criar e executar as migrations, é hora de criar uma classe para cada tabela, que é chamada de modelo (model), que ficarão na pasta app. Cada modelo estende a classe Model e o nome deve ser em camel case, com o nome da classe começando com letra maiúscula. Então, se o nome da tabela for esqueci_senha, o nome do modelo será EsqueciSenha.

Um modelo pode ser criado com um comando com o seguinte formato:

php artisan make:model <nome_modelo>

Se usar a convenção do Laravel de nome de tabela, onde o nome de tabela é no plural com relação ao modelo representado (ex: tabela users e classe User), não é necessário atribuir valor ao campo $table do modelo. Porém, essa não é a convenção que usamos quando aprendemos banco de dados. Se uma tabela representar alunos, ela se chamará aluno e não alunos. Portanto, o seu modelo deve ter o seguinte campo:

protected $table = '<nome_tabela>';

O mesmo deve ser feito para a chave primária caso ela não seja a padrão, ou seja, id:

protected $primaryKey = '<nome_coluna>';

Todo campo a ser preenchido que vier de um formulário, que não for automaticamente gerado, como o id, que é auto-incremental, deve estar no vetor $fillable:

protected $fillable = ['<nome_coluna_1>', … , '<nome_coluna_n>'];

Um campo auto-incremental de outra tabela, que é uma chave estrangeira, não deve estar presente no vetor acima, mas deve ser passado à tabela relacionada manualmente através de atribuição.

Caso haja um ou mais campos que devam ser protegidos, como senhas e tokens para relembrar senha, eles devem estar no vetor $hidden. Obviamente, devem estar em $fillable também.

protected $hidden = ['<nome_coluna_1>', … , '<nome_coluna_n>'];

Por fim, o modelo deve incluir métodos para retornar os objetos dos modelos relacionados via chave estrangeira. Se o relacionamento for 1-1 ou 1-n, o modelo da tabela que contém a chave estrangeira deve conter um método como abaixo, supondo que a tabela tabela_1 tenha uma chave estrangeira para tabela_2:

public function tabela2()
{
	return $this->belongsTo('App\Tabela2');
}

Já o modelo da tabela que é referenciada deve conter um método como se o relacionamento for 1-1:

public function tabela1()
{
	return $this->hasOne('App\Tabela1');
}

Se o relacionamento for 1-n, o modelo da tabela que é referenciada deve conter um método como:

public function tabela1s()
{
	return $this->hasMany('App\Tabela1');
}

Não é preciso se preocupar com o caso de relacionamentos n-m, já que são resolvidos com tabela de junção, formando dois relacionamentos 1-n.

Um exemplo de modelo genérico juntando todas as informações acima fica da seguinte forma, considerando que tabela_2 tem chave estrangeira para tabela_1 em um relacionamento 1-1:

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Tabela1 extends Model
{
    	protected $table = 'tabela_1';
	protected $primaryKey = 'chave_primaria';
    	protected $fillable = [
		'campo_1',
        	...
        	'campo_n',
    ];

    protected $hidden = [
        	'campo_x1',
		...
    		'campo_xn,
	];
    
    public function tabela2()
    {
       return $this->hasOne('App\Tabela2');
    }
}

Nos modelos também deve-se colocar métodos que vão consultar/alterar/inserir dados no banco. Esses métodos devem ser estáticos e, quando forem consultas, retornar os dados desejados baseados em filtros que serão passados em consultas ao banco. Não se deve acessar o banco diretamente do controller e sim chamar esses métodos dos modelos. Assim, se o modo como a alteração no banco é feita precisar ser modificado, mas com a mesma semântica, o código não precisará ser alterado em todos os pontos que a consulta for chamada. Em Laravel, é possível acessar e alterar os dados das tabelas com métodos que consultam e/ou alteram a tabela sem passar o comando SQL inteiro e usando estaticamente a classe do modelo, o chamado Eloquent, evitando o problema de segurança chamado SQL injection e simplificando a sintaxe. Por exemplo, em um modelo ModelName, pode-se ter o seguinte método para buscar a primeira linha do banco de dados filtrando pelo campo field_name:

public static function getByField($field_value)
{
	return ModelName::where('field_name', $field_value)->first();
}    

Outras maneiras de se acessar/alterar o banco em um modelo usando o Eloquent podem ser vistas em https://laravel.com/docs/5.2/eloquent. Algo interessante é que o método save() pode ser usado tanto para criar como para alterar dados do banco, simplificando a programação.

Algo interessante é que os métodos que retornam dados do banco, se não tratados e mandados diretos para o navegador, mostrarão um JSON. Isso torna o Laravel muito útil para a implementação de web services.

Instalando Novos Componentes

Muitas vezes será necessário instalar uma biblioteca nova para a aplicação. Para isso, usa-se o Composer. Para instalar um novo pacote para a aplicação, use o comando:

composer require <nome_pacote>

Pode-se também editar diretamente o arquivo composer.json do seu projeto e colocar o pacote que deseja em “require”: e depois rodar o comando composer update. Em https://packagist.org/ é possível ver os pacotes disponíveis.

Alguns pacotes úteis: laravelcollective/html (formulários HTML) xavrsl/cas (autenticação) e overtrue/laravel-lang (idiomas). Para editá-los diretamente no composer.json, é preciso colocar diretamente a versão, ficando algo como:

"require": { 
     "php": ">=5.5.9", 
     "laravel/framework": "5.2.*", 
     "laravelcollective/html": "5.2", 
     "overtrue/laravel-lang": "~3.0",
     "xavrsl/cas": "1.2.*" 
},

Ao instalar um componente, pode ser necessário criar um ou mais aliases para acessá-lo em config/app.php no vetor aliases. Assim, ao importar uma classe, o comando use ficará mais simples, pois não será necessário usar o caminho todo da mesma. Adicionalmente, todo pacote deve ser adicionado ao vetor providers (Service Providers) para poder ser usado.

Para os pacotes citados acima, deve-se trocar em providers: Illuminate\Translation\TranslationServiceProvider::class por Overtrue\LaravelLang\TranslationServiceProvider::class

e adicionar

Collective\Html\HtmlServiceProvider::class,
Xavrsl\Cas\CasServiceProvider::class

Já em aliases, deve-se colocar:

'Form'      => Collective\Html\FormFacade::class,
'Html'      => Collective\Html\HtmlFacade::class,
'Cas' 	    => Xavrsl\Cas\Facades\Cas::class,

Para trocar o idioma, altere em config/app.php o locale para pt-BR. Finalmente, para copiar o idioma desejado de vendor para resources/lang/, faça o comando

php artisan lang:publish pt-BR

Note-se que este comando não funciona automaticamente no Windows porque ele precisa do comando cp. Pode-se copiar os arquivos na mão simplesmente baixando os arquivos de https://github.com/caouecs/Laravel-lang/tree/master/src/pt-BR e copiando-os para a nova pasta resources/lang/pt-BR. Alternativamente, pode-se instalar o pacote Cygwin de http://cygwin.com/ para ter no prompt de comando os comandos de Linux.

Em https://packagist.org há vários pacotes úteis para muitas funcionalidades, para que sua aplicação não precise “reinventar a roda”. Em geral, para cada pacote, há instruções de como usá-lo, seja com o Laravel ou apenas com PHP.

Views

Uma view é uma tela HTML que vai receber parâmetros em PHP, usando de preferência as facilidades do Laravel, passados pelo controller, o que será visto posteriormente, para a exibição de dados. As views ficam na pasta resources/views. Elas devem ser organizadas em pastas de acordo com as funcionalidades do seu sistema. Por exemplo, um sistema onde haja telas diferentes de acesso para aluno, professor e administrador, pode ter pastas com esses nomes com views para cada tipo de usuário. Uma maneira de organizar essas pastas é ter uma pasta por controller. Por padrão, existe a pasta errors para views que exibirão erros. Se o sistema for mandar e-mails com HTML, é interessante haver uma pasta tal como emails para ter views com o HTML que será usado nos e-mails.

Uma view tem que ter a extensão .blade.php. Contudo, na hora de se referir a ela no controller, o formato a ser usado é

<pasta>.<subpasta_1>. … .<subpasta_n>.<nome_da_view_sem_o_blade>

Então, se por exemplo uma pasta aluno contiver uma pasta chamada dados e dentro dela houver um arquivo de view chamado cadastro.blade.php (caminho resources/views/aluno/dados/cadastro.blade.php), a view será acessada como aluno.dados.cadastro.

Templates

Em geral um sistema terá telas que terão código HTML em comum. Como é uma péssima prática repetir o código, usa-se templates para torná-lo mais fácil de entender. Laravel te ajuda a fazer um template de forma muito fácil.

Um template é uma página web do PHP padrão que fica no diretório views, mas com “pedaços” que serão preenchidos nas páginas que seguirem esse template. Portanto, os templates também são views, porém com sessões incompletas que precisam ser preenchidas pelas views propriamente ditas. Um template tem sessões que são declaradas em uma linha com formato @yield('<nome_sessao>') e as views que a usarem precisam ter o seguinte formato:

@extends('<nome_template>')
...
@section('<nome_sessao_1>')
...
@stop
...
@section('<nome_sessao_n>')
…
@stop

Um template pode estender outro template e esse processo pode ser feito em cascata para aproveitar a estrutura já existente e evitar a repetição desnecessária de código. Nesse caso, o nome das sessões devem ser diferentes para não dar conflito.

Views Parciais

Às vezes uma parte de uma view será repetida em várias views. Ao invés de se criar um template, cria-se uma view parcial, que será incluída nas views que precisarem desse pedaço de código usando:

@include('<nome_da_view>')  

Obviamente, uma view parcial não faz sentido existir sozinha. Esse problema pode ser resolvido com templates, porém quando se tratar de trechos de códigos isolados que serão repetidos, faz mais sentido usar views parciais.

Facilidades

Uma facilidade que existe no Laravel é o fato de não ser necessário usar muito código PHP diretamente nas views. Ao invés de usar comandos de controle em PHP, é possível usar comandos começados com @ para fazer a mesma coisa. Um if-then-else, por exemplo, usa os comandos @if, @else e @endif. Repare que todos os comandos que existem precisam de um comando para finalizá-lo. Já as variáveis em PHP que aparecem em uma view são passadas como parâmetro em um vetor e são acessadas começando por $. Por exemplo, se ao chamar uma view de um controller se passar como parâmetro um vetor dados com a chave mensagem ($dados[‘mensagem] = ‘erro’;), a mensagem deve ser acessada na view usando $mensagem.

Se usar o altamente aconselhável pacote de formulários collective, é possível simplificar a construção de formulários. Cada campo do formulário será criado usando Form:: juntamente com o que se deseja cololocar no HTML da view. Os campos devem estar entre (para dados escapados, mais seguro, o que deve ser usado quase sempre) ou {!! ||} (para dados não escapados). Para saber o que tem disponível e exemplos, acesse https://laravelcollective.com/docs/5.2/html.

Se estiver usando o grupo de middleware web nas rotas que dão para as views que usam o template base de todo o sistema (algo altamente recomendável), é possível fazer um tratamento dos erros de entrada de dados de maneira centralizada. Fazendo-se código similar ao mostrado abaixo no template base, consegue-se tratar erros genéricos, erros de formulário (entrada) e sucessos de forma centralizada. Note-se o uso de classes do bootstrap.

@if (isset($erro))
   <section class="row">
      <div class="col-sm-8 col-md-6 col-lg-6 col-sm-offset-2 col-md-offset-3 col-lg-offset-3 alert alert-warning">
         <p style="font-size: 12pt;"><b>ERRO</b><br/>{!! $erro !!}</p>
      </div>
   </section>
@endif

@if (isset($sucesso))
   <div style="width: 40%; float: none; margin: 0 auto;">
      <div class="panel-body">
         <p class="alert alert-success">{{ $sucesso }}</p>
      </div>
   </div>
@endif

@if ($errors->any())
   <section class="row">
      <div class="col-sm-8 col-md-6 col-lg-6 col-sm-offset-2 col-md-offset-3 col-lg-offset-3 alert alert-warning">
         <p style="font-size: 12pt;"><b>ERRO</b>
            @foreach ($errors->all() as $error)
               <br/>{{ $error }}
            @endforeach
         </p>
      </div>
   </section>
@endif

Estilos

Toda página HTML tem estilos para formatá-la de acordo com o desejado. Para isso, tem-se CSS, JavaScript, fontes e imagens. Todos os arquivos referentes a estilos devem ficar na pasta public.

Em geral, coloca-se os arquivos CSS na subpasta css, os arquivos JavaScript na subpasta js, os arquivos de fontes na subpasta fonts e os arquivos de imagens na subpasta img.

Para deixar os arquivos de estilos independentes do endereço raiz da aplicação, eles devem ser importados usando a função asset() de maneira escapada na hora de referenciar o caminho do arquivo a ser importado.

Lembre-se de que scripts devem ser preferencialmente carregados ao final das páginas, pois se um script der erro, a página em si não deixará de ser carregada.

Rotas

As rotas são os endereços relativos pelos quais é possível acessar as páginas da aplicação web. Se o endereço raiz for o padrão, http://localhost:8000/public/, a rota que aponta para a raiz é /. Num projeto recém criado, vem apenas uma rota que redireciona para a view de boas vindas. Esse exemplo redireciona diretamente para uma view, uma tela HTML por ser uma tela sem funcionalidades. Porém, se a tela tiver alguma interação com o usuário, coloca-se o nome da rota juntamente com o método de um controller a ser chamado, que por sua vez vai carregar, possivelmente passando dados, uma view. Para depuração, pode-se retornar também uma string.

É muito útil, como dito anteriormente, usar um middleware, seja para fazer autenticação, seja para colocar as mensagens de erro de forma padrão, tal como acontece ao usar o grupo de middleware web. Portanto, usa-se esse tipo de código para declarar que um grupo de rotas usa um determinado middleware ou grupo de middleware em app\Http\routes.php:

Route::group(['middleware' => ['<middleware>']], function ()
{
   ...
});

Se um grupo de rotas usar mais de um middleware ou grupo de middleware, faz-se:

Route::group(['middleware' => ['<middleware_1>', ..., '<middleware_n>']], function ()
{
   ...
});

Além do web, um muito usado é o cas (que precisa ser criado) para fazer autenticação central. Neste caso, apenas as rotas do sistema que precisam de autenticação precisam usar esse grupo de middleware.

Já as rotas propriamente ditas ficam no seguinte formato, usando-se um método de um controller:

Route::get('<nome_rota>', '<nome_controller>@<metodo>');

ou

Route::post('<nome_rota>', '<nome_controller>@<metodo>');

Uma rota com Route::get() é uma rota que apresentará uma tela. O <nome_rota> aparecerá depois do endereço da página raiz. Então, se digitar http://localhost:8000/public/<nome_rota>, o método <nome_metodo> do controller nome_controller será invocado. Se essa rota precisar de autenticação, por causa do middleware, por exemplo, será direcionado a uma página para se autenticar e depois será redirecionado para a rota pedida.

Já uma rota com Route::post() é resultante da submissão de um formulário. Ela não pode ser acessada diretamente. O nome da rota vai ser a mesma usada no correspondente Route::get() que abrirá a página, mas chamará um outro método que será responsável pelo processamento de dados enviados pelo usuário.

Rotas podem receber parâmetros, que serão passados na barra de endereço após o nome da rota. Para isso, após o nome da rota em Route::get(), passar /{<nome_parametro>}. Pode-se passar mais de um parâmetro, um após o outro, separados por /. Se algum parâmetro for opcional, faz-se: /{<nome_parametro?>}. Se uma rota tiver o mesmo nome de uma rota com parâmetro, a sem parâmetro deve ficar acima da com parâmetro em app\Http\routes.php. Senão, ao tentar acessar a rota sem parâmetro, o Laravel vai buscar a primeira opção e achar que está tentando acessar uma rota com parâmetro sem o parâmetro e vai dar erro.

Ao escolher o nome de um rota, evite usar underline e sim use o hífen, para facilitar a digitação da rota pelo usuário do sistema, que não precisará ficar usando combinação de teclas, o que acelerará a digitação da mesma.

Controllers

O controller é onde se coloca a lógica do sistema. É ele quem carrega e passa os dados para as views e manda os modelos fazerem alterações no banco.

Os controllers ficam na pasta app\Http\Controllers, e podem ser criados através do comando:

php artisan make:controller <nome_controller>

Lembre-se de que o nome do controller deve ficar em camel case.

O controller deve ter como métodos públicos todos os métodos que aparecem como funcionalidade das rotas. Adicionalmente, pode-se ter métodos privados adicionais auxiliares.

As métodos públicos para as rotas que recebem parâmetros podem ter como parâmetros os passados para a rota. Se o parâmetro passado for uma chave primária de uma tabela e o parâmetro for declarado como tendo o tipo de seu respectivo modelo, o Laravel já pega o objeto da tabela representado por aquele modelo automaticamente. Para isso funcionar, o nome do parâmetro da rota tem que ser idêntico ao nome do parâmetro do método, obviamente sem o $ característico de variáveis em PHP.

Já os métodos públicos para as rotas do tipo POST devem ter como parâmetro um Request, que será explicado a seguir, para fazer a validação de dados submetidos por um formulário. Se for desejado voltar para a rota GET que originou o POST na hora da submissão do formulário, o método que trata a rota POST deve terminar com

return back();

O número de controllers em uma aplicação varia de acordo com a estrutura da aplicação. Pode-se ter um controller por um grupo de views que pertencem a um mesmo grupo de funcionalidades. Por exemplo, se uma aplicação for acessada por alunos, professores e administradores, pode-se ter um controller para cada tipo de usuário. Em geral, cada pasta das views terá um controller.

Envio de E-mails

Muitos sistemas precisam enviar e-mails. Para isso, preenche-se no .env variáveis de ambiente para a configuração de e-mail. No caso da TIC, os parâmetros devem ser:

MAIL_DRIVER=smtp
MAIL_HOST=<nome_host>
MAIL_PORT=587
MAIL_USERNAME=<nome_usuario>
MAIL_PASSWORD=<senha>
MAIL_ENCRYPTION=tls

Os campos nome_host, nome_usuario e senha devem ser preenchidos de acordo com o endereço de e-mail escolhido. Entre em contato com o suporte para conseguir credenciais de e-mail para seu sistema.

Já o envio de e-mail propriamente dito é feito pelo controller. Além disso, é interessante criar uma view para formatar o e-mail. Se o sistema for mandar mais do que um tipo de e-mail, é interessante ter um template para padronizar os e-mails e uma view para cada tipo de e-mail.

Para mandar um e-mail, o controller deve ter um código semelhante ao abaixo, onde em use deve-se passar parâmetros se o e-mail do destinatário, nome do destinatário, assunto, e-mail do remetente e nome do remetente forem variáveis:

try
{
   Mail::send('<nome_da_view>', $params, function ($menssagem) use (...)
   {
      $menssagem->to('<e-mail do destinatario>', '<nome do destinatario>')->subject('<assunto>');
      $menssagem->from('<e-mail do remetente>', '<nome do remetente>');
   });
  
   ...

}
catch(\Exception $exception)
{
   ...
}

Requests

Toda vez que um formulário é submetido, é desejado que seus dados sejam validados para que informação espúria ou inválida seja inserida no banco de dados. O banco pode até impedir algumas inconsistências, como campos vazios. Porém, além da validação no banco, é importante haver validação no formulário. Para impedir inconsistências, cria-se um Request para cada rota de POST. Esse Request é passado como parâmetro para o respectivo método POST. Antes mesmo de o método ser chamado, a validação é feita automaticamente e, se algum dado estiver inválido, a mesma tela será mostrada com as mensagens de erro mostrando os campos errados se tiver seguido as recomendações para centralizar as mensagens de erro no template ao usar o grupo de middleware web.

Por padrão, as mensagens de erro de validação serão todas em inglês. Para colocá-las em português brasileiro, é necessário instalar o pacote de português brasileiro como já explicado anteriormente.

Para cada método que for tratar um POST, ou seja, a submissão de um formulário, cria-se uma classe Request com o seguinte comando:

php artisan make:request <nome_request>

Por padrão, a classe fica em camel case com o nome da validação seguido pela palavra Request. Um exemplo poderia ser CadastroAlunoRequest. Os Requests ficam na pasta app/Http/Requests.

O nome da classe de Request deve ser usado como o tipo do Request no método que trata a requisição POST. Então, o método que trata a submissão de um formulário de cadastro de aluno vai ter como parâmetro algo como:

CadastroAlunoRequest $request

Para se pegar os dados vindos da submissão, use o método Request::all() no parâmetro passado para pegar o vetor associativo com os mesmos.

Já na classe de Request criada, o que se deseja é colocar as regras de validação no método rules(), que deve retornar um vetor associativo. Cada chave do vetor é o nome do campo do formulário e seu respectivo valor é uma string com as validações necessárias separadas pelo caractere |. Então, se o formulário tiver um campo login e ele não puder ser ausente, menor do que 21 caracteres e maior do que 5 caracteres, sua regra fica assim:

'login' => 'required|min:6|max:20'

Se tiver dois campos que precisam de confirmação, algo comum para obrigar o usuário a redigitar o e-mail ou a senha a ser criada, o campo de confirmação deve ter o mesmo nome do original seguido de _confirmation. Já no Request, o campo original deve ter um confirmed para assegurar que os dois valores são iguais.

Já se a validação desejada é que um campo seja único numa tabela do banco de dados, a regra é unique:<table_name>. Desta forma, o controller não precisará consultar a tabela após receber os dados para verificar se aquele valor já foi usado antes.

Algo interessante é que se uma ou mais validações falharem e se tiver colocado a impressão de mensagens de erro centralizada no template base, será possível ver todos os erros nos dados inseridos no formulário de maneira detalhada, facilitando a correção dos mesmos pelo usuário.

As validações pré-existentes podem ser vistas em https://laravel.com/docs/5.2/validation#available-validation-rules.

É muito comum em sistemas brasileiros desejar validar CNPJ, CPF e CEP e essas regras não existem nas validações pré-existentes. Para criar uma, primeiro cria-se uma classe chamada, por exemplo, de CustomValidator em app/Http. Ela deve ter o seguinte formato:

<?php
   namespace App\Http;

   use Illuminate\Validation\Validator;

   class CustomValidator extends Validator
   {
   }

Para cada tipo de validação, criam-se dois métodos: um com a regra para validar o dado e outro para mostrar a mensagem de erro. Se o objetivo for criar uma validação para CPF, faz-se algo como:

public function validateCpf($attribute, $cpf, $parameters)
{
   if ($cpf é válido) // Colocar aqui a programação que valida o CPF passado.
      return TRUE
   return FALSE;
}

protected function replaceCpf($message, $attribute, $rule, $parameters)
{
   return "O CPF é inválido.";
}

Por último, é necessário publicar o validador customizado em app\Providers\AppServiceProvider.php. No método boot(), coloca-se

Validator::resolver(function($translator, $data, $rules, $messages)
{
   return new CustomValidator($translator, $data, $rules, $messages);
});

Assim, agora basta usar cpf nas regras de validação. Se quiser fazer regras para CNPJ e CPF, basta adicionar um par de métodos de nomenclatura similar para validar o dado de entrada e a mensagem de erro.

Com validação nos requests a programação é bastante simplificada porque quase não será necessário fazer ifs para a validação de dados de entrada. Quase tudo será tratado automaticamente pelo Laravel.

Autenticação

Uma maneira fácil de usar autenticação de usuários no Laravel sem ter que se preocupar com a lógica disso é criando uma estrutura semi-pronta que cuida disso. Para isso, o Laravel tem o comando:

php artisan make:auth

Com isso, serão criados controllers, views, migrations, model, rotas e estilos para cuidar da questão. Isso deve ser a primeira coisa a ser criada na aplicação se for mesmo usar isso. Afinal, será complicado criar a aplicação toda e só depois colocar um módulo de autenticação.

Algo a se notar é que as views não usam o Collective. Isso pode ser incorporado às demais que serão criadas no sistema e não é um problema. O estilo pode ser mudado com outros CSSs.

Algo que necessariamente tem que ser mexido são os caminhos para os estilos, que não serão encontrados ao rodar o sistema do NetBeans e provavelmente de outros endereços. Eles devem ser modificados para usar o método asset(). Além disso, os estilos importam CSSs que estão na web, quando o ideal seria baixá-los e colocá-los no sistema, pois podem ficar fora do ar, embora isso seja improvável por serem do Google. Alguns estilos que estão declarados diretamente nas views também devem ser separados.

Um problema é que a linguagem da interface terá que ser traduzida manualmente, já que está tudo em inglês e escrito diretamente nas views.

Após isso, é preciso configurar o banco de dados e rodar as migrations. Para rodar completamente o projeto, é necessário também configurar o envio de e-mail em .env, juntamente com um endereço de remetente geral do sistema em config/mail.php, editando o valor da chave from com o nome e endereço de e-mail do remetente.

Tendo a parte de autenticação pronta, funcional e já bem testada pelos desenvolvedores do framework, agora é mudar os estilos caso necessário e adicionar outros, a página inicial (que não vai ser de Laravel), o título, e continuar a programação do sistema.

Algo interessante a se fazer é criar um projeto template só com a autenticação, tirar as referências a Laravel, traduzi-lo, consertar os links de estilos e colocar estilos que estão dentro das views em CSSs externos, e criar o projeto para o NetBeans. Quando for criar um novo projeto que usa autenticação, é só copiar o projeto e renomear as referências para o nome do projeto final.

Essa parte de autenticação pode ser completamente ignorada se usar o CAS da UFRJ para autenticação de usuários. Obviamente, o CAS só pode ser usado para sistemas internos que serão usados por só por usuários cadastrados na UFRJ e que podem usar a intranet.

Middlewares

Os middlewares processam requisições ao acessar uma rota antes de ir para a rota desejada propriamente dita. Isso é necessário porque certas rotas precisam de autenticação, não podem ser acessadas por determinados usuários, ou para compartilhar variáveis de erro, algo que acontece quando se usa o grupo de middleware web. Elas podem ser um grupo ou individual. Uma grupo de middleware deve ser usado quando precisar que vários middlewares sejam usados pelas mesmas rotas. Se olhar o arquivo app/Http/Kernel.php, verá que o grupo web possui vários middlewares. Mais abaixo, há os middlewares individuais.

Para criar um middleware, use o comando

php artisan make:middleware <nome_middleware>

O método handle() deve ser modificado para o middleware ter alguma ação antes de completar a requisição ou mesmo impedi-la. Por padrão, esse método apenas completa a requisição.

Após isso, crie um middleware ou um grupo de middleware que o contenha. Agora, é só usá-lo.

Se for um middleware de CAS, primeiramente é necessário instalar os pacotes necessários via Composer. Após isso, em config/app.php, adicione Xavrsl\Cas\CasServiceProvider::class a providers e 'Cas' ⇒ Xavrsl\Cas\Facades\Cas::class a aliases.

Após isso, crie um Middleware semelhante ao abaixo:

<?php 
namespace App\Http\Middleware;

use Closure;
use Session;
use Cas;
use App\Usuario;

class CasMiddleware 
{
   /**
    * Handle an incoming request.
    *
    * @param  \Illuminate\Http\Request  $request
    * @param  \Closure  $next
    * @return mixed
    */
   public function handle($request, Closure $next)
   {
      Cas::authenticate();  
      if (Cas::isAuthenticated())
      {
         ...
      }
      else
      {
         ...
      }
      return $next($request);
   }
}

Por fim, crie um middleware ou grupo de middleware chamado cas que contenha a classe nova, que será algo como: \App\Http\Middleware\CasMiddleware::class.

Nas versões do Laravel a partir da 5.3 não é preciso colocar o web como middleware porque ele já vem automaticamente para todas as rotas por ser muito usado.

Sessões

Sessões servem para salvar dados de uma instância do sistema que está rodando no navegador. Em geral, é muito utilizado para salvar dados de um usuário logado e saber se há um usuário válido logado.

Para colocar dados na sessão, faz-se:

Session::put('<nome_chave'>, '<nome_valor>')

Já para recuperar dados da sessão ou saber se há uma sessão válida, faz-se:

Session::get('<nome_chave'>')

Com isso, pode-se saber se há uma chave com aquele nome ou se o valor que corresponde aquela chave é válido ou o procurado.

Para finalizar uma variável de sessão, faz-se:

Session::forget('<nome_chave'>')

Por fim, para finalizar todas as sessões, faz-se:

Session::flush()

CAS

Além do que já foi dito, são precisos mais alguns passos para poder usar o CAS em sua aplicação. Primeiramente, deve-se publicar a funcionalidade do CAS baixada no diretório vendor:

php artisan vendor:publish

Depois, em .env, deve-se colocar:

CAS_HOSTNAME=<nome_do_host>
CAS_URI=<nome_do_caminho_do_cas>

Se for usar o CAS da TIC, a configuração fica apenas com o CAS_HOSTNAME=cas.tic.ufrj.br. Já se for o da UFRJ, também só precisa de CAS_HOSTNAME=cas.ufrj.br.

Toda rota que precisar passar pela autenticação do CAS precisa estar dentro do grupo de middleware cas.

Toda a vez que precisar saber no controller se há um usuário autenticado no CAS, faz-se:

Cas::isAuthenticated()

Já para finalizar a sessão no CAS, provavelmente quando se desejar finalizar a sessão no sistema (log out) que o usa, faz-se:

Cas::logout(['service' => asset('<nome_rota>')]);

onde <nome_rota> é a rota para onde o sistema deve ser redirecionado após o log out.

Funções Auxiliares

O Laravel usa várias funções auxiliares globais, conhecidas como helper functions. Pode ser interessante criá-las para seu projeto sem ter que criar uma classe com métodos estáticos. Isso simplifica a sintaxe e, por sua vez, a programação.

Para fazê-lo, crie um arquivo PHP, por exemplo helpers.php em app. Para que as funções possam ser usadas sem imports ou algo do gênero, precisam ser auto-carregadas. Para isso, coloque em na seção autoload do composer.json algo como:

"files":
[
   "app/helpers.php"    
]

Para que o Laravel detecte as funções, é necessário dar o comando composer dump-auto.

Dump and Die

Uma maneira costumeira de se depurar em PHP é dar var_dump(), print_r() ou echo em uma variável e depois o comando die para parar a execução do sistema após imprimir o valor, com maior ou menor detalhe, de uma variável no navegador. O Laravel facilita isso com o dump and die ou dd(), que irá fazer um dump no objeto em questão e parar a aplicação.

Recomendações Adicionais

* Cuidado com os name spaces. Se for usar uma classe, é preciso importá-la usando o comando use no cabeçalho da classe que vai usá-la. Senão, o Laravel vai achar que a classe está no name space da classe sendo editada. Se for uma classe do PHP como Exception ou String, é necessário chamá-las com \Exception e \String, respectivamente. Senão, o Laravel achará que essas classes estão dentro do name space da classe sendo editada.

* Se for usar a autenticação criada pelo Laravel, seu projeto deve começar daí. Posteriormente, crie as migrations e models. Só depois comece a implementação do sistema propriamente dita.

* Dependendo do que for fazer em seu controller, redirecionamentos podem ser muito úteis. O método redirect ou o facade Redirect devem ser usados. Em http://laraveldaily.com/all-about-redirects-in-laravel-5/ há várias maneiras de se lidar com redirecionamentos.

* Sempre use as versões mais recentes do PHP 5 e Laravel 5, seja por questôes de segurança, seja por novas funcionalidades, principalmente no Laravel. Se lançarem a versão 6 do Laravel, provavelmente terá muitas diferenças em relação à 5, assim como aconteceu entre a 4 e a 5, o que poderá tornar difícil seguir este tutorial.

* Use a classe Carbon para tratar data e hora por possuir vários métodos extremamente úteis. Para usá-la, apenas importe Carbon\Carbon por ela já vir instalada com o Laravel.

Mail

“Laravel provides a clean, simple API over the popular SwiftMailer library with drivers for SMTP, Mailgun, SparkPost, Amazon SES, PHP's mail function, and sendmail, allowing you to quickly get started sending mail through a local or cloud based service of your choice.”

Mail com Laravel