Tutorial Laravel para iniciantes - Parte 04 [Controller e Injeção de dependência]

Nesse post vamos organizar a aplicação Laravel criando uma classe que será responsável por controlar requisições pertinentes ao gerenciamento de mensagens. Vamos também tentar entender a injeção de dependência (IoC) na prática.


Glossário:



Injeção de dependência -IoC- (Dependency Injection, em inglês) é um padrão de desenvolvimento de programas de computadores utilizado quando é necessário manter baixo o nível de acoplamento entre diferentes módulos de um sistema. Nesta solução as dependências entre os módulos não são definidas programaticamente, mas sim pela configuração de uma infraestrutura de software (container) que é responsável por "injetar" em cada componente suas dependências declaradas. A Injeção de dependência se relaciona com o padrão Inversão de controle, mas não pode ser considerada um sinônimo deste.

1) Criando o Controller

Agora vamos criar a classe ContatoControler que estende a classe Controller, a forma mais fácil e rápida de fazer isso é utilizando o poderoso artisan:
php artisan make:controller ContatoController
O comando a cima basicamente cria a classe ContatoController estendida da classe Controller, dentro do diretório "app/Http/Controllers".
Resultado do comando php artisan make
Agora no Arquivo criado cole dentro da classe ContatoControler crie os métodos index(); enviar(); e listar();:
namespace App\Http\Controllers;

use Illuminate\Http\Request;
use App\Contato;

class ContatoController extends Controller
{
    
 /* Exibe o formulário para enviar uma mensagem */ 
 public function index(){ 
  return view('welcome');
 } 
 /** 
 * Insere a mensagem no banco de dados
 */
 public function enviar(Request $request){
  $contato = new Contato();
  $contato->nome = $request->get('nome');
  $contato->email = $request->get('email');
  $contato->mensagem = $request->get('mensagem');
  $contato->save();
  echo "Sua mensagem foi armazenada com sucesso! Código: " . $contato->id;
 } 

 /**
 * Exibe uma listar com as mensagens cadastradas 
 */ 
 public function listar(){
  return view('listar', array('contatos' => Contato::all()));
 }
}
Aqui criamos os 3 métodos, onde o index(); carrega a view('welcome'); o enviar(); insere os dados no banco de dados e listar(); onde carrega a view('listar');.

2) Configurando as rotas

Agora que já temos ContatoController, vamos editar e corrigir as nossas rotas, acesse o arquivo web.php dentro do diretório routes, remova todo o seu conteúdo e substitua pelas seguintes rotas:
/*
|--------------------------------------------------------------------------
| 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('/', 'ContatoController@index');
Route::post('/enviar', 'ContatoController@enviar');
Route::get('/listar', 'ContatoController@listar');
Aqui criamos asas 3 rotas respectivamente relacionadas ao que criamos nos ContatoController.

Entendendo o IoC Container do Laravel

Observe o método enviar() da classe ContatoController
/** * Insere a mensagem no banco de dados */ 
public function enviar(Request $request){
 $contato = new Contato();
 $contato->nome = $request->get('nome');
 $contato->email = $request->get('email');
 $contato->mensagem = $request->get('mensagem');
 $contato->save();
 echo "Sua mensagem foi armazenada com sucesso! Código: " . $contato->id; 
}
Desde a segunda parte desse tutorial já estamos trabalhando com injeção de dependência do Laravel, ao colocar o parâmetro Request $request o Laravel já cria a instância da classe Request para que possamos utilizar dentro do nosso método, em outras palavras isso é o IoC do Laravel trabalhando.
Poderíamos também utilizar o IoC para criar a instância da classe Contato. Vamos ao Exemplo:
/** * Insere a mensagem no banco de dados */
public function enviar(Request $request, Contato $contato){
 $contato->nome = $request->get('nome');
 $contato->email = $request->get('email');
 $contato->mensagem = $request->get('mensagem');
 $contato->save();
 echo "Sua mensagem foi armazenada com sucesso! Código: " . $contato->id; 
} 
Repare que não foi necessário criar a instância da classe Contato, pois já está sendo passada pelo parâmetro com isso já sendo instanciada na variável $contato, agilizando significativamente o trabalho, recomendo testar non no nosso controle de exemplo (ContatoController) para afixar melhor!

Bindings o que é?

O contêiner de serviço Laravel é uma ferramenta poderosa para gerenciar dependências de classe e executar injeção de dependência. Injeção de dependência é uma frase de fantasia que significa essencialmente isso: dependências de classe são "injetadas" na classe através de um construtor ou, em alguns casos, "setter" métodos. (Laravel - Service Container)

Utilizar o IoC para classes concretas é desperdício, isso fica mais interessante quando trabalhamos com interfaces.

Vamos imaginar o seguinte exemplo:
Ao inserir os dados de contato no Banco de Dados iremos enviar um e-mail de notificação para o usuário, a primeiro momento poderíamos enviar utilizando a classe Mail do Laravel, mas como é um exemplo vamos criar assim mesmo u.u.

Crie o arquivo NotificarEmail.php dentro diretório app:
namespace App;
class NotificarEmail 
{
    public function notificar(){ 
     /*
     * Código que manda email ..... 
     */
     echo "
 Email enviado com sucesso! E Lembrando é só um exemplo!";
    }
}
Criamos a classe NotificarEmail com o método notificar(); que para esse exemplo tem a função de imprimir apenas o texto.

Agora vamos adicionar esse novo método no parâmetro de do método enviar(); em ContatoController:
/** * Insere a mensagem no banco de dados */
 public function enviar(Request $request, Contato $contato, \App\NotificarEmail $notificar){
   $contato->nome = $request->get('nome');
   $contato->email = $request->get('email');
   $contato->mensagem = $request->get('mensagem');
   
   $contato->save();
   echo "Sua mensagem foi armazenada com sucesso! Código: " . $contato->id;

   // Notificando!!!!
  $notificar->notificar(); 
 } 
Note que adicionamos o parâmetro relacionado a classe Contato e agora temos também a Classe NotificarEmail
Exemplo da saída do nosso teste
Agora vamos extrapolar mais ainda nosso exemplo e criar mais 2 tipos de métodos de notificação: Notificação com Carta dos Correios e Notificação com Galinha Voadora. Agora vamos criar as interfaces de notificação para essas classes implementar.

Interfaces de objetos permitem a criação de códigos que especificam quais métodos uma classe deve implementar, sem definir como esses métodos serão tratados.
Interfaces são definidas da mesma forma que classes, mas com a palavra-chave interface substituindo class e com nenhum dos métodos tendo seu conteúdo definido.
Todos os métodos declarados em uma interface devem ser públicos, essa é a natureza de uma interface.
Crie o arquivo NotificacaoInterface.php dentro do diretório App:
namespace App;

interface NotificacaoInteraface {
 public function interface();
}
Agora faça com que a Classe NotificacaoEmail implemente esta Interface NotificacaoInterface:
namespace App;

class NotificarEmail implements NotificarInterface
{
 public function notificar(){
  echo "Email enviado com sucesso! e Lembrando é só um exemeplo!";
 }
}
Basicamente adicionamos o implements em NotificarEmail.

Agora vamos Criar as classes NotificarGalinhaVoadora e NotificarCartaCorreios dentro do diretório App:
NotificarGalinhaVoadora.php
namespace App; 

class NotificarGalinhaVoadora implements NotificacaoInterface
{
 public function notificar(){
  /*
  * Código que é mais rapido que os Correios a Galinha Voadora
  * Jogadores do Ocarina of Time sabe o que to falando!
  */
  echo "Sua carta chegando a velocidade da luz e além!";
 }
}
NotificarCartaCorreios.php
namespace App;
 
class NotificarCartaCorreios implements NotificacaoInterface
{
 public function notificar(){
  /*
  * Seria um código de exemplo para os correios trabalharem mais rapido
  */
  echo "Parabéns sua Carta Chegou, porem fora do prazo";
 }
}
Agora vamos trocar na classe ContatoControler no método enviar o parâmetro NotificarEmail pelo NotificacaoInterface:
/** 
 * Insere a mensagem no banco de dados
 */
 public function enviar(Request $request, Contato $contato, \App\NotificacaoInterface $notificar){
  $contato->nome = $request->get('nome');
  $contato->email = $request->get('email');
  $contato->mensagem = $request->get('mensagem');
  $contato->save();
  echo "Sua mensagem foi armazenada com sucesso! Código: " . $contato->id; 
  $notificar->notificar();
 } 
Agora vamos enviar os dados do formulário novamente e ver o resultado.
Erro, qual interface escolher ?
Ué, porque ocorreu o erro? O Laravel não conseguiu descobrir qual interface deveria instanciar. Agora que entra o Bindings. Com o "bind" você informa qual classe deve ser instanciada  quando uma interface for injetada. Para ficar mais claro vamos a um exemplo prático.

Resolvendo problema do Laravel carregar uma tela em branco


Antes disso vamos a um problema que aconteceu comigo, no meu servidor Linux em vez de imprimir o erro ele simplesmente carregou uma tela em branco sem nenhum erro ou informação, na maioria dos casos quando ocorria um erro ele simplesmente carregava uma tela branca, então como resolver de o Laravel carregar uma tela branca ?
Na raiz do projeto rode os seguintes comandos:
# Group Writable (Group, User Writable)
$ sudo chmod -R gu+w storage

# World-writable (Group, User, Other Writable)
$ sudo chmod -R guo+w storage
Pelo que entendi o problema ocorre devido as permissões para que o Apache "www-data" possa escrever no diretório em questão. Fazendo isso seu problema é solucionado! Agora continue com o exemplo!


Abra o arquivo AppServiceProvider.php dentro do diretório app/Providers, e adicione a bind o método register();
/**
     * Register any application services.
     *
     * @return void
     */
    public function register()
    {
        $this->app->bind(\App\NotificacaoInterface::class, \App\NotificarGalinhaVoadora::class);
    }
Resultado após criação do bind

Imagine o poder de usar interfaces, pois ao usar a interface eu desacoplo classes. Para o ContatoController não importa se a notificação será feita pela Galinha ou pelos Correios. 
Agora imagine se amanhã queria enviar uma notificação por SMS, não será preciso abrir o Controller. Basta criar uma classe que implemente a NotificacaoInterface e alterar o bind. 
Para fixar melhor uma boa ideia e brincar com os bind, por exemplo troque as outras implementações que criamos no bind e veja o resultado!

Conclusão:

Nesse post aprendemos melhor como funcionam as rotas, trabalhamos com criação de classes Controller, fizemos uso do IoC, também fizemos criação de interfaces não ligadas as classes em si, nesse post aprendemos bastante! Recomendo a releitura dele (eu mesmo o fiz) para uma melhor fixação.



Se vocês gostaram desse Post não deixe de compartilhar com seus amigos!!!
E para não perder nenhuma novidade nos sigam nas redes sociais:
Twitter: @Bulfaitelo
Facebook: Bulfaitelo Project
Blogger: Bulfaitelo Project
Share on Google Plus

About Thiago Rodrigues

Formado em Sistema de Informação pela Faculdade Paraíso
O que falar de mim? Não á muito, mas garanto que meu objetivo aqui é somente ajudar!
Atualmente desenvolvendo o projeto do QiEstudo.

Comentários
0 Comentários

0 comentários:

Postar um comentário

Observação: somente um membro deste blog pode postar um comentário.