Zend Expressive
Autor: Paulo Vitor Lima | Publicado: 2016-03-11T19:34:00-03:00

Nesse breve tutorial vou registrar algumas descobertas para rodar um projetinho no zend expressive (micro framework do zend), com suporte ao postgres.

Requisitos


PHP 7.0.3 (cli);

Extensão: pdo-pgsql;

Composer 1.0-dev;
Postgres 9.4;





Clonando o esqueleto
Execute o comando abaixo, em um diretório a escolha:

$&nbsp;composer create-project zendframework/zend-expressive-skeleton example


Ao fazer isso você será questionado sobre quais módulos serão carregados, eu escolhi:


Full skeleton&nbsp;(opção default);
FastRoute&nbsp;(opção default);
Zend ServiceManager (opção default);
Zend View (opção 3);
Whoops;


Depois atualize o composer:



$&nbsp;composer update




Instalando algumas dependências opcionais com composer

Eu gosto sempre de usar o Debug do Zend, e também sou fã do padrão de projeto, Table Data Gateway, descrito por Martin Fowler no livro "Patterns of Enterprise Application Architecture", sob o número: 466.



$&nbsp;composer require zendframework/zend-db zendframework/zend-debug





Testando a instalação



Rode o sistema usando:

$ php -S localhost:80 -t public/



Você poderá verificar o sucesso através das páginas:


http://localhost/
http://localhost/api/ping





Configurando o acesso ao Postgres



Vamos criar o arquivo de configuração dentro de diretório que a aplicação irá ler automaticamente:




&lt;?php

return [

&nbsp; &nbsp; 'db' =&gt; [

&nbsp; &nbsp; &nbsp; &nbsp; 'driver' &nbsp; =&gt; 'Pdo',

&nbsp; &nbsp; &nbsp; &nbsp; 'dsn' &nbsp; &nbsp; &nbsp;=&gt; 'pgsql:host=localhost;port=5432;',

&nbsp; &nbsp; &nbsp; &nbsp; 'database' =&gt; 'postgres',

&nbsp; &nbsp; &nbsp; &nbsp; 'user' &nbsp; &nbsp; =&gt; 'postgres',

&nbsp; &nbsp; &nbsp; &nbsp; 'password' =&gt; 'postgres'

&nbsp; &nbsp; ],

];




Salve dentro do diretório: &lt;projeto&gt;/config/autoload/, com o nome: "database.global.php".

Perceba que eu utilizei o nome de usuário, senha e nome do banco de dados como postgres. Ajuste!



Altere o arquivo de configuração: "dependencies.global.php", adicione ao array dependencies-&gt;factories, mais um valor:

Zend\Db\Adapter\Adapter::class =&gt; Zend\Db\Adapter\AdapterServiceFactory::class





Feito isso, já fica registrado a conexão com o banco de dados.



Adicionando o objeto de banco às requisições



Utilize uma factory para fazer a inicialização da classe que vai responder a requisição, do "middleware", adicione o trecho a seguir para injetar a dependência:




&nbsp; &nbsp; &nbsp; &nbsp; $db = $container-&gt;get('Zend\Db\Adapter\Adapter');

&nbsp; &nbsp; &nbsp; &nbsp; return new HomePageAction($router, $template, $db);


Utilize um nome qualquer, como por exemplo, DatabaseHelperMiddlewareFactory para a classe "factory";


Na classe que realmente irá fazer a ação (por exemplo, HomePageAction), iremos adicionar o terceiro parâmetro ao método construtor e copiá-lo como membro da classe.



private $db;


public function __construct(Router\RouterInterface $router, Template\TemplateRendererInterface $template = null, $db)

&nbsp; &nbsp; {

&nbsp; &nbsp; &nbsp; &nbsp; $this-&gt;router &nbsp; = $router;

&nbsp; &nbsp; &nbsp; &nbsp; $this-&gt;template = $template;

&nbsp; &nbsp; &nbsp; &nbsp; $this-&gt;db = $db;

&nbsp; &nbsp; }




Nesse ponto, já é possível utilizar o "this-&gt;db", e realizar consultas. Mas ainda falta utilizar o table data gateway.




Criando abstrações das tabelas




O que eu mais gosto nesse padrão é a não necessidade de transformar o conteúdo da tabela em objeto de negócio. Então vamos criar um diretório para guardar esse tipo de classe, criaremos:



&lt;projeto&gt;/src/App/Model/





Vamos criar uma classe como o exemplo abaixo:




&lt;?php



namespace App\Model;



use Zend\Db\TableGateway\TableGateway;

use Zend\Db\Sql\TableIdentifier as TableIdentifier;

class Usuario extends TableGateway

{

&nbsp; &nbsp;&nbsp;

&nbsp; &nbsp; public function __construct($table, $adapter, $features = null, $resultSetPrototype = null, $sql = null){

&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;

&nbsp; &nbsp; &nbsp; &nbsp; return parent::__construct(

&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; new TableIdentifier('tb_usuario', 'pessoal'),&nbsp;

&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; $adapter,&nbsp;

&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; $features,&nbsp;

&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; $resultSetPrototype,&nbsp;

&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; $sql

&nbsp; &nbsp; &nbsp; &nbsp; );

&nbsp; &nbsp; }

}






A classe Usuario, estende a classe TableGateway que tem os métodos de acesso aos dados, eu só sobrescrevi o método construtor para marcar o nome da tabela e o esquema que a tabela utiliza. Para usar a combinação nome da tabela e nome do esquema, eu tive que instanciar um "TableIdentifier".



Agora, vamos voltar, na nossa action, e utilizar nossa abstração da tabela de banco de dados:





use App\Model\Usuario as Model;



e no método onde se faz a ação:



$model = new Model(null, $this-&gt;db);

$data = $model-&gt;select()-&gt;toArray();



Nesse exemplo, eu fiz um select * from pessoal.tb_usuario, e joguei o resultado como array, na variável $data;



Simples assim.