Implementando Laravel



Documentos relacionados
Laravel: De Aprendiz a Artesão (Brazilian Portuguese)

UX Design Para Startups

Dominando Action Script 3

Entendendo como funciona o NAT

Curso de PHP. FATEC - Jundiaí. A programação orientada a objetos (object-oriented oriented programming

Um objeto é uma instância de uma 'classe'. Você define uma classe utilizando o trecho de código abaixo;

Orientação a Objetos

Parte I. Demoiselle Mail

AULA 4 VISÃO BÁSICA DE CLASSES EM PHP

PARANÁ GOVERNO DO ESTADO

Prototype, um Design Patterns de Criação

NOKIA. Em destaque LEE FEINBERG

EXERCÍCIOS SOBRE ORIENTAÇÃO A OBJETOS

Protocolo TCP/IP. Neste caso cada computador da rede precisa de, pelo menos, dois parâmetros configurados:

SUMÁRIO 1. AULA 6 ENDEREÇAMENTO IP:... 2

Na Figura a seguir apresento um exemplo de uma "mini-tabela" de roteamento:

Arquitetura de Rede de Computadores

IP significa Internet Protocol. A Internet é uma rede, e assim como ocorre em qualquer tipo de rede, os seus nós (computadores, impressoras, etc.

Autor: Ricardo Francisco Minzé Júnior - ricardominze@yahoo.com.br Desenvolvendo aplicações em camadas com PHP 5.

Microsoft Access: Criar relações para um novo banco de dados. Vitor Valerio de Souza Campos

MANUAL DO ANIMAIL Terti Software

Implementando uma Classe e Criando Objetos a partir dela

Especificação do 3º Trabalho

ARRAYS. Um array é um OBJETO que referencia (aponta) mais de um objeto ou armazena mais de um dado primitivo.

NOVIDADES DO JAVA PARA PROGRAMADORES C

UNIDADE V COMO CONSEGUIR LEADS

AirPort Express: configurações iniciais

Programação Orientada a Objetos Classes Abstratas Técnico em Informática. Prof. Marcos André Pisching, M.Sc.

DEFINIÇÃO DE MÉTODOS

Web Design Aula 11: Site na Web

PHP INTRODUÇÃO CLASSES E OBJETOS

Criando & Consumindo um WebService com ASP.NET 2.0 Publicado em: 25 de Agosto de 2007 Por Herman Ferdinando Arais

Java 2 Standard Edition Como criar classes e objetos

Desenvolvendo plugins WordPress usando Orientação a Objetos

Introdução ao Tableau Server 7.0

DESENVOLVIMENTO DE SOFTWARE. Introdução ao Visual Studio VB.Net. Programação Estruturada. Prof. Celso Candido ADS / REDES / ENGENHARIA

Reuso com Herança a e Composiçã

Java para Desenvolvimento Web

Curso: Redes II (Heterogênea e Convergente) Tema da Aula: Características Roteamento

Tabela e Gráficos Dinâmicos Como estruturar dinamicamente dados no Excel

AJAX no GASweb. Mas e afinal, para que usamos o AJAX?

Autor: Marcelo Maia

TUTORIAL PRÁTICO SOBRE Git. Versão 1.1

ATRIBUTOS PRIVADOS 6. ENCAPSULAMENTO MÉTODOS PRIVADOS MÉTODOS PRIVADOS

UNIVERSIDADE FEDERAL DO PARANÁ

Barra de ferramentas padrão. Barra de formatação. Barra de desenho Painel de Tarefas

Computação II Orientação a Objetos

Manual de Utilizador. Disciplina de Projecto de Sistemas Industriais. Escola Superior de Tecnologia. Instituto Politécnico de Castelo Branco

APOSTILA DE REDES DE COMPUTADORES PARTE - I I

2 Orientação a objetos na prática

ÍNDICE... 3 INTRODUÇÃO A série... 4

Programação Orientada a Objetos Herança Técnico em Informática. Prof. Marcos André Pisching, M.Sc.

COMO FUNCIONA NOSSA CONSULTORIA DE MARKETING DIGITAL ESPECIALIZADA EM VENDAS ONLINE

ProgramaTchê programatche.net Programação OO com PHP

Introdução a Java. Hélder Nunes

Engenharia de Software III

Programação por Objectos. Java

Análise e Desenvolvimento de Sistemas ADS Programação Orientada a Obejeto POO 3º Semestre AULA 03 - INTRODUÇÃO À PROGRAMAÇÃO ORIENTADA A OBJETO (POO)

Google Drive. Passos. Configurando o Google Drive

GUIA MUDANÇA E FORMATAÇÃO DE SERVIDOR - SLIM

Como Localizar Uma Pessoa Da Sua Família Em Qualquer Lugar do Mundo. Por Mcgill Dias

FERRAMENTAS DE COLABORAÇÃO CORPORATIVA

Análise e Projeto de Sistemas

Desenvolvendo Websites com PHP

GUIA MUDANÇA E FORMATAÇÃO DE SERVIDOR - MILLENNIUM

POO Programação Orientada a Objetos. Classes em Java

Antes de tudo... Obrigado!

Entrar neste site/arquivo e estudar esse aplicativo Prof. Ricardo César de Carvalho

10 DICAS DE TECNOLOGIA PARA AUMENTAR SUA PRODUTIVIDADE NO TRABALHO

OCOMON PRIMEIROS PASSOS

sobre rogério gonçalves gerente de projetos > digitale agência digital rogerio@digitale.com.br h7p:// h7p://leveme.

Na disciplina de Cálculo Numérico, vamos trabalhar com a linguagem C++ e o compilador que vamos usar é o Dev C++.

Curso de Informática Básica

Padrões de Projeto. Singleton

APOSTILA DE EXEMPLO. (Esta é só uma reprodução parcial do conteúdo)

INTRODUÇÃO À TECNOLOGIA SERVLETS

E-BOOK LINK DE OURO. DE: IMPÉRIO DO PTC PARA VOCÊ: CLICADOR Espalhe este ELO juntando-se ao nosso Grupo: IMPÉRIO DO PTC!

PROGRAMAÇÃO ORIENTADA A OBJETO EM PHP

Permissões de compartilhamento e NTFS - Parte 1

Trecho retirando do Manual do esocial Versão 1.1

2 echo "PHP e outros.";

1) Ao ser executado o código abaixo, em PHP, qual será o resultado impresso em tela?

Manual do Ambiente Moodle para Professores

FERRAMENTAS DE COLABORAÇÃO CORPORATIVA

Inicialização Rápida do Novell Vibe Mobile

Tutorial: Webmail. Dicas de Uso e Funcionalidades 02/2015. Versão 01

3 Dicas MATADORAS Para Escrever s Que VENDEM Imóveis

DNS DOMAIN NAME SERVER

DNS DOMAIN NAME SERVER

Bruno Jurkovski Lucas Fialho Zawacki. Site do curso:

PHP: Formulários e upload de múltiplos arquivos Por Alfred Reinold Baudisch 28 de fevereiro de 2006.

INTRODUÇÃO: 1 - Conectando na sua conta

Adapti - Technology Solutions Leonor cardoso nº 331 Fone : (041) Curitiba - PR MANUAL DO USUÁRIO

PROGRAMAÇÃO ESTRUTURADA. CC 2º Período

Acessando um Banco de Dados

Programação Orientada a Objetos: Lista de exercícios #1. Bruno Góis Mateus

Transcrição:

Implementando Laravel Chris Fidao and Antonio Carlos Ribeiro This book is for sale at http://leanpub.com/implementinglaravel-pt This version was published on 2013-09-28 This is a Leanpub book. Leanpub empowers authors and publishers with the Lean Publishing process. Lean Publishing is the act of publishing an in-progress ebook using lightweight tools and many iterations to get reader feedback, pivot until you have the right book and build traction once you do. 2013 Chris Fidao (traduzido por Antonio Carlos Ribeiro)

Conteúdo Conceitos Básicos....................................... 1 O Contêiner............................................ 2 Uso Básico............................................ 2 Indo Para Algo Mais Avançado................................. 3 Inversão de Controle...................................... 3 Uso no Mundo Real....................................... 5 Injeção de Dependência...................................... 7 O que é Injeção de Dependência?............................... 7 Criando Novas Dependências no Controlador......................... 8 Interfaces como Dependências................................. 9 Por que Injeção de Dependência?............................... 11 Conclusão............................................ 14

Conceitos Básicos Ao longo deste livro nós vamos fazer uso de alguns dos recursos mais poderosos do Laravel. Antes de começar é importante, pelo menos, saber algo sobre o contêiner do Laravel e como ele nos permite usar mais facilmente a Injeção de Dependência (Dependency Injection). Este capítulo vai falar sobre o contêiner do Laravel, seu uso da Inversão de Controle (Inversion of Control) e da Injeção de Dependência.

O Contêiner A classe Illuminate\Foundation\Application é quem faz a amarração de tudo o que há no Laravel. Esta classe é um contêiner - ela pode conter dados, objetos, classes e até closures (funções anônimas). Uso Básico Para ver como o contêiner funciona, vamos ver fazer um exercício no nosso arquivo de rotas (routes). O contêiner do Laravel implementa a interface ArrayAccess e assim sendo é possível acessá-lo como se fosse um array. Vamos usá-lo como um array associativo: 1 Route::get('/container', function() 2 { 3 // Retorna a instância da Aplicação 4 $app = App::getFacadeRoot(); 5 6 $app['some_array'] = array('foo' => 'bar'); 7 8 var_dump($app['some_array']); 9 }); Apontando o browser para a rota /container, teremos este resultado: 1 array (size=1) 2 'foo' => string 'bar' (length=3) Assim vemos que a Application (classe App acima), mesmo sendo uma classe com atributos e métodos está acessível como se fosse um array. Facades Não entendeu o que App::getFacadeRoot() faz? A classe App é uma fachada (Facade). Isso permite seu uso em qualquer lugar, acessando-a de maneira estática. Entretanto ela não é uma classe estática. O método getfacaderoot retorna a instância real da classe, que nós precisávamos a fim de usá-la como um array no exemplo. Veja esta e outras Facades no namespace Illuminate\Support\Facades.

O Contêiner 3 Indo Para Algo Mais Avançado Agora um uso mais sofisticado do contêiner, vamos atribuir a ele uma closure. 1 Route::get('/container', function() 2 { 3 // Retorna a instância da Aplicação 4 $app = App::getFacadeRoot(); 5 6 $app['say_hi'] = function() 7 { 8 return "Hello, World!"; 9 }; 10 11 return $app['say_hi']; 12 }); Novamente, apontando para a rota /container vamos ver: 1 Hello, World! Embora aparentemente simples, isso é realmente muito poderoso. Isso é, de fato, a base de como os vários pacotes Illuminate interagem entre si, formando o Laravel framework. Mais adiante vamos ver como os Provedores de Serviço (Service Providers) vinculam itens ao contêiner, funcionando como elo de ligação entre os vários pacotes Illuminate. Inversão de Controle A classe Container do Laravel possui muito mais cartas na manga do que apenas parecer ser um array. Ela também pode funcionar como contêiner de Inversão de Controle (IoC - do inglês Inversion of Control). Inversão de Controle é uma técnica que nos permite definir como a nossa aplicação deve implementar uma classe ou uma interface. Por exemplo, se a nossa aplicação possui como dependência FooInterface e nós queremos usar uma implementação dela, cuja classe vamos chamar de ConcreteFoo, o contêiner IoC é aonde definimos esta implementação. Vamos ver um exemplo básico de como isso funciona usando nossa rota /container, novamente. Primeiro vamos definir algumas classes - uma interface e uma classe que a implementa, estas podem ser colocadas diretamente no arquivo app/routes.php:

O Contêiner 4 1 interface GreetableInterface { 2 3 public function greet(); 4 5 } 6 7 class HelloWorld implements GreetableInterface { 8 9 public function greet() 10 { 11 return 'Hello, World!'; 12 } 13 } Agora vamos usar essas classes como nosso contêiner, para ver o que dá pra fazer. Primeiro vou introduzir o conceito de ligação (binding). 1 Route::get('/container', function() 2 { 3 // Retorna a instância da Aplicação 4 $app = App::getFacadeRoot(); 5 6 $app->bind('greetableinterface', function() 7 { 8 return new HelloWorld; 9 }); 10 11 $greeter = $app->make('greetableinterface'); 12 13 return $greeter->greet(); 14 }); Ao invés de usar o (acessível como array) $app['greetableinterface'], usamos o método bind(). Ele configura o contêiner IoC do Laravel, para que este devolva uma instância da classe HelloWorld toda vez que for solicitado pela interface GreetableInterface. Desta forma podemos mudar implementações! Por exemplo, ao invés de HelloWorld, eu poderia criar uma nova implementação, chamá-la de GoodbyeCruelWorld e decidir que o contêiner a devolva sempre que alguém solicitar GreetableInterface. Isso nos leva ao encontro da manutenibilidade da nossa aplicação. Usando o contêiner nós podemos (de forma ideal) mudar implementações em determinados pontos sem afetar outras áreas do código da nossa aplicação.

O Contêiner 5 Uso no Mundo Real Onde na sua aplicação você vai colocar todas essas ligações? Se você não quer abarrotar os arquivos start.php, filters.php, routes.php e outros arquivos envolvidos na inicialização com ligações, então você pode usar classes Provedoras de Serviços (Service Providers). Provedores de Serviço são criados especificamente para registrar as ligações feitas ao contêiner do Laravel. De fato praticamente todos os pacotes Illuminate usam um Provedor de Serviço para fazer apenas isso. Vamos ver um exemplo de como Provedores de Serviços são usados em um pacote Illuminate. Examinemos o pacote Pagination. Primeiro, aqui está o método register() do Provedor de Serviço Pagination: 1 public function register() 2 { 3 $this->app['paginator'] = $this->app->share(function($app) 4 { 5 $paginator = new Environment( 6 $app['request'], 7 $app['view'], 8 $app['translator'] 9 ); 10 11 $paginator->setviewname( 12 $app['config']['view.pagination'] 13 ); 14 15 return $paginator; 16 }); 17 } O método register() é executado automaticamente em cada Provedor de Serviço especificado no arquivo app/config/app.php. E o que está acontecendo nesse método register()? Em primeiro lugar, e acima de tudo, ele registra a instância do paginator no contêiner. Isso disponibilizará $app['paginator'] e App::make('paginator') para uso em outras áreas da aplicação. Em seguida ele define a instância do paginator como retorno (resultado) de uma closure, exatamente como fizemos no exemplo say_hi.

O Contêiner 6 O método Share em $this->app->share() apenas provê um caminho para que a closure seja utilizada como um singleton (garantia de apenas uma instância). Esta closure cria um novo objeto Pagination\Environment, altera nele um parâmetro de configuração e o devolve. Você provavelmente notou que o Provedor de Serviço usa outras ligações com a aplicação. A classe PaginationEnvironment claramente possui algumas dependências no seu método construtor ( construct): um objeto request ($app['request']), um objeto view ($app['view']) e um objeto translator ($app['translator']). Felizmente estas ligações são criadas em outros pacotes do Illuminate, definidas em diversos Provedores de Serviços. Podemos, assim, ver como os diversos pacotes Illuminate interagem entre si. Devido ao fato deles estarem ligados ao contêiner da aplicação, nós podemos usá-los em outros pacotes (ou em nosso próprio código!), sem amarar nosso código a uma classe específica.

Injeção de Dependência Agora que sabemos como o contêiner funciona, vamos ver como nós podemos usá-lo para implementar Injeção de Dependência no Laravel. O que é Injeção de Dependência? Injeção de Dependência (Dependency Injection) é o ato de injetar (introduzir) qualquer dependência no momento da instanciação de uma classe, ao invés de invés de instanciar as dependências em algum lugar dentro próprio código da classe. Frequentemente dependências são definidas como indução de tipo (type-hinting), que é forçar que os parâmetros de um método construtor sejam objetos de uma determinada classe. Veja este método construtor, por exemplo: 1 public function construct(helloworld $greeter) 2 { 3 $this->greeter = $greeter; 4 } Ao forçar (induzir) que o parâmetro $greeter seja do tipo HelloWorld, estamos afirmando explicitamente que a classe depende de uma instância de HelloWorld. Opostamente, esta é uma instanciação direta: 1 public function construct() 2 { 3 $this->greeter = new HelloWorld; 4 } Se você está se perguntando o porquê de se usar Injeção de Dependência, esta resposta no Stack Overflow¹ é um ótimo ponto de partida. Eu vou cobrir alguns dos benefícios dela nos exemplos que seguem. A seguir vamos ver um exemplo de Injeção de Dependência em ação, usando o contêiner IoC do Laravel. ¹http://stackoverflow.com/questions/130794/what-is-dependency-injection

Injeção de Dependência 8 Criando Novas Dependências no Controlador Este é um caso de uso bem comum em Laravel. Normalmente, criarmos um controlador que precisa receber uma classe instanciada em seu método construtor ( construct), nós precisaremos passar essas dependências (sob a forma de parâmetros) quando a classe for criada. Mas o que acontece quando você cria uma dependência em um controlador Laravel? Você vai precisar instanciar o controlador manualmente a fim de solucionar a dependência (enviá-la através de parâmetro). Veja um exemplo: 1 $crtl = new ContainerController( new HelloWorld ); Isso é ótimo, mas ninguém instancia controladores diretamente em Laravel - o roteador lida com isso para nós. Nós podemos, entretanto, injetar as dependências do controlador através do uso do contêiner IoC do Laravel! Mantendo as mesmas classes GreetableInterface e HelloWorld de antes, vamos imaginar agora que ligamos nossa rota /container a um controlador: Arquivo: app/routes.php 1 interface GreetableInterface { 2 3 public function greet(); 4 5 } 6 7 class HelloWorld implements GreetableInterface { 8 9 public function greet() 10 { 11 return 'Hello, World!'; 12 } 13 } 14 15 Route::get('/container', 'ContainerController@container); Agora em nosso novo controlador, podemos definir HelloWorld como um parâmetro no método construtor:

Injeção de Dependência 9 Arquivo: app/controllers/containercontroller.php 1 class ContainerController extends BaseController { 2 3 protected $greeter; 4 5 // Dependência da classe: HelloWorld 6 public function construct(helloworld $greeter) 7 { 8 $this->greeter = $greeter; 9 } 10 11 public function container() 12 { 13 return $this->greeter->greet(); 14 } 15 16 } Agora execute a rota /container e você deve, novamente, ver: 1 Hello, World! Observe, porém, que nós não fizemos nenhuma ligação no contêiner. Ele simplesmente funcionou - uma instância de HelloWorld foi automaticamente enviada ao controlador. Isso aconteceu porque o contêiner IoC tenta resolver qualquer dependência definida no método construtor de um controlador. E Laravel vai injetar as dependências necessárias para nós! Interfaces como Dependências Mas nós ainda não terminamos, finalmente chegamos ao que queríamos mostrar. E se ao invés de especificar HelloWorld como dependência do controlador, nós especificássemos a interface GreetableInterface? Vamos ver como fica:

Injeção de Dependência 10 1 class ContainerController extends BaseController { 2 3 protected $greeter; 4 5 // Dependência da classe: GreetableInterface 6 public function construct(greetableinterface $greeter) 7 { 8 $this->greeter = $greeter; 9 } 10 11 public function container() 12 { 13 echo $this->greeter->greet(); 14 } 15 16 } Se tentarmos executar como está, vamos receber o seguinte erro: 1 Illuminate\Container\BindingResolutionException: 2 Target [GreetableInterface] is not instantiable A classe GreetableInterface, claro, não é instanciável, porque ela é uma interface. Mas podemos ver que Laravel está tentando instanciá-la, para resolver a dependência definida na classe. Resolvendo isso - nosso controlador depende de uma instância de GreetableInterface, então vamos então usar o método bind() do contêiner para indicar ao Laravel que ele deve enviar uma instância de HelloWorld: 1 interface GreetableInterface { 2 3 public function greet(); 4 5 } 6 7 class HelloWorld implements GreetableInterface { 8 9 public function greet() 10 { 11 return 'Hello, World!'; 12 } 13 }

Injeção de Dependência 11 14 15 // Ligando a classe HelloWorld quando for solicitada uma instância de 16 // GreetableInterface aqui!! 17 App::bind('GreetableInterface', 'HelloWorld'); 18 19 Route::get('/container', 'ContainerController@container); Agora execute a rota /container e você deve ver Hello, World! novamente! Note que eu não usei uma função anônima para ligar a HelloWorld - Você pode simplesmente passar o nome da classe concreta como uma string, se preferir. Uma closure é útil quando a implementação tem as suas próprias dependências que precisam ser passadas no método construtor. Por que Injeção de Dependência? Por que nós queremos especificar uma interface como dependência ao invés de uma classe concreta? Porque precisamos que toda classe definida no construtor seja uma subclasse de uma interface. Desta forma podemos com segurança usar qualquer implementação, porque o método que precisamos sempre estará disponível. Em outras palavras e de forma sucinta: podemos mudar a implementação à vontade, sem afetar outras porções do código da nossa aplicação. Aqui vai um exemplo de algo que precisei fazer muitas vezes em aplicações reais. Não copie e cole este exemplo. Estou omitindo alguns detalhes, tal como o uso de variáveis de configuração para chaves de API, para ficar mais claro. Vamos dizer que sua aplicação envia e-mails usando o AWS da Amazon. Para tal foi definida uma interface Emailer implementada na classe AwsEmailer:

Injeção de Dependência 12 1 interface Emailer { 2 3 public function send($to, $from, $subject, $message); 4 } 5 6 class AwsEmailer implements Emailer { 7 8 protected $aws; 9 10 public function construct(awssdk $aws) 11 { 12 $this->aws = $aws; 13 } 14 15 public function send($to, $from, $subject, $message) 16 { 17 $this->aws->addto($to) 18 ->setfrom($from) 19 ->setsubject($subject) 20 ->setmessage($message); 21 ->sendemail(); 22 } 23 } Ligamos Emailer à implementação AwsEmailer: 1 App::bind('Emailer', function() 2 { 3 return new AwsEmailer( new AwsSDK ); 4 }); O controlador tem a interface Emailer como dependência:

Injeção de Dependência 13 1 class EmailController extends BaseController { 2 3 protected $emailer; 4 5 // Class dependency: Emailer 6 public function construct(emailer $emailer) 7 { 8 $this->emailer = $emailer; 9 } 10 11 public function email() 12 { 13 $this->emailer->send( 14 'ex-to@example.com', 15 'ex-from@example.com', 16 'Peanut Butter Jelly Time!', 17 "It's that time again! And so on!" 18 ); 19 20 return Redirect::to('/'); 21 } 22 23 } Vamos em seguida supor que no futuro o escopo da sua aplicação cresca e passe a precisar de funcionalidades do que a AWS não provê. Depois de alguma procura e pesar de opções, você decide pelo SendGrid. Como você vai fazer para migrar a sua aplicação para o SendGrid? Devido ao fato de estar usando interfaces e o contêiner IoC do Laravel, migrar para o SendGrid é fácil! Primeiro, crie uma implementação da interface Emailer que use SendGrid! 1 class SendGridEmailer implements Emailer { 2 3 protected $sendgrid; 4 5 public function construct(sendgridsdk $sendgrid) 6 { 7 $this->sendgrid = $sendgrid; 8 } 9 10 public function send($to, $from, $subject, $message)

Injeção de Dependência 14 11 { 12 $mail = $this->sendgrid->mail->instance(); 13 14 $mail->addto($to) 15 ->setfrom($from) 16 ->setsubject($subject) 17 ->settext( strip_tags($message) ) 18 ->sethtml($message) 19 ->send(); 20 21 $this->sendgrid->web->send($mail); 22 } 23 } Em seguida (e por último), configure a aplicação para usar SendGrid ao invés de AWS. Por ter nossa chamada a bind() no contêiner IoC, alterar a implementação do Emailer de AwsEmailer para SendGridEmailer é tão simples quanto esta mudança: 1 // De 2 App::bind('Emailer', function() 3 { 4 return new AwsEmailer( new AwsSDK ); 5 }); 6 7 // Para 8 App::bind('Emailer', function() 9 { 10 return new SendGridEmailer( new SendGridSDK ); 11 }); Note que fizemos isso sem alterar uma linha de código em qualquer outro ponto da nossa aplicação. Impor o uso da interface Emailer como dependência, garante que qualquer classe injetada sempre terá o método send() disponível. Podemos ver isso em nosso exemplo. O controlador continua chamando $this->emailer->send() e não teve que ser modificado quando mudamos a implementação de AwsEmailer para SendGridEmailer. Conclusão Injeção de Dependência e Inversão de Controle são padrões exaustivamente utilizados no desenvolvimento em Laravel. Como você verá, vamos definir várias interfaces a fim de tornar nosso código manutenível e ajudar nos testes. O contêiner IoC do Laravel torna isso fácil para nós.