sábado, 10 de outubro de 2015

Formulários com Zend

O Framework Zend 2, possui um recurso muito interessante, e prático, que é a possibilidade de se criar formulários separados da camada de visão.
No início pode parecer meio confuso, ou até mesmo desnecessário, mas conforme vamos utilizando, vemos sua total praticidade:
  • A possibilidade de incluir ou remover um campo sem mexer, e possivelmente quebrar, o HTML;
  • Definir um campo como necessário ou não;
  • Trocar o nome do campo do formulário;
  • Tratar a validação do formulário e etc.

Vamos fazer um exemplo prático que será utilizado futuramente para gravar um registro no banco de dados.
Vamos abrir o Eclipse PDT e criar a pasta “Form” dentro de “module/Usuario/src/Usuario”
Dentro da pasta Form, que acabamos de criar, vamos criar o arquivo CadastroForm.php com o seguinte conteúdo:


<?php
namespace Usuario\Form;

use Zend\Form\Form;

class CadastroForm extends Form {
      
       public function __construct($fieldset) {
             parent::__construct($fieldset);
             $this->setAttribute('method', 'post');
             $this->add(array(
                           'name' => 'nome',
                           'attributes' => array(
                                  'type' => 'text',
                           ),
                           'options' => array(
                                  'label' => 'Nome',
                           )
             ));
             $this->add(array(
                           'name' => 'email',
                           'attributes' => array(
                                  'type' => 'text',
                           ),
                           'options' => array(
                                  'label' => 'Email',
                           ),
             ));
             $this->add(array(
                           'name' => 'password',
                           'attributes' => array(
                                  'type' => 'password',
                           ),
                           'options' => array(
                                   'label' => 'Senha',                   
                           ),
             ));
             $this->add(array(
                           'name' => 'submit',
                           'attributes' => array(
                                  'type' => 'submit',
                                  'value' => 'Gravar',
                                  'id' => 'submitbuton',
                           ),
             ));
       }
}




Nosso CadastroController.php, agora, ficou assim:

<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/ZendSkeletonApplication for the canonical source repository
 * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Usuario\Controller;

use Zend\Mvc\Controller\AbstractActionController;
use Zend\View\Model\ViewModel;
use Usuario\Form\CadastroForm;

class CadastroController extends AbstractActionController
{
    public function indexAction()
    {
        return new ViewModel();
    }
   
    public function adicionarAction() {
       $form = new CadastroForm('cadastro');
       $form->get('submit')->setValue('Cadastrar');
       return array('form' => $form);
    }
   
    public function apagarAction() {
      
    }
   
    public function editarAction() {
      
    }
}


Vamos exibir agora o nosso formulário. Abra o arquivo adicionar.phtml da pasta “module/Usuario/view/usuario/cadastro” e cole o seguinte código:

<?php
$title = 'Novo Cadastro';
$this->headtitle($title);
?>

<h1><?=$this->escapehtml($title) ?></h1>

<?php
$form = $this->form;
$form->setAttribute('action', $this->url('cadastro', array('action' => 'adicionar')));
$form->prepare();
?>

<?=$this->form()->openTag($form)?>
<?=$this->formCollection($this->form)?>
<?=$this->form()->closeTag($form)?>



Agora, quando acessarmos nossa rota de adicionar, que criamos no post de rotas, deveremos ter essa saída:



Explore a documentação do Zend para a lista completa dos atributos

sábado, 3 de outubro de 2015

Criando as rotas no Framework Zend 2

Nas publicações anteriores, aprendemos a instalar o Zend, configurar o Doctrine e criamos o novo módulo Usuário a partir do módulo padrão Application.

Vamos configurar as rotas de acesso desse novo módulo, ou seja, quando digitarmos no endereço do navegador:

nossa-aplicacao/rota/acao
Iremos executar alguma ação. Salvar, editar, excluir ou alterar. Funções básicas de um CRUD.

A rota pode ser qualquer nome que iremos escolher que apontará para o módulo que queremos trabalhar. Temos o módulo Usuário e nossa rota, se você quiser, não precisa, necessariamente, se chamar usuário. Podemos chamar de cadastro, por exemplo. ;)

Com o nosso Eclipse PDT aberto no nosso projeto teste vá até o arquivo /module/Usuario/config/module.config.php
Como esse módulo é uma cópia inteira do módulo Application, podemos observar que todo o arquivo faz referência às configurações do módulo Application. Vamos configurar ele para o nosso novo módulo.

O que está grifado de amarelo é para ser ajustado.

O que está grifado de vermelho é para ser excluído.

Vou colar o código original aqui, e vamos analisar as mudanças passo-a-passo para ficar mais fácil:




Já que trocamos o nome do arquivo IndexController.php para CadastroController.php, abra o arquivo e faça o seguinte ajuste dentro da classe.


Adicione também os métodos:

public function adicionarAction() {}
public function apagarAction() {}
public function editarAction() {}

Abra o arquivo index.phtml e exclua todo o seu conteúdo.
Escreva “Teste” e salve o arquivo.

Acrescente os arquivos:
adicionar.phtml
apagar.phtml
editar.phtml


Todos com letras minúsculas.

Pronto! Agora já podemos acessar a nossa aplicação e a nova rota que criamos está disponível :D
Podemos acessar pelos links:
/cadastro
/cadastro/adicionar
/cadastro/apagar
/cadastro/editar






sábado, 26 de setembro de 2015

Configurando o Doctrine (Symfony 2) no Framework Zend 2

Vamos agora configurar o DOCTRINE para conectar com o nosso banco de dados.

Antes de mais nada, vamos instalar o Eclipse PDT para poder facilitar a nossa vida. O Eclipse PDT é uma IDE modificada para ajudar a compilar nosso código com a API do PHP.



No menu do Eclipse escolha: New > PHP Project from Existing Directory

Informe um nome para o projeto e o local onde baixamos o esqueleto da aplicação e instalamos as dependências no post anterior com o COMPOSER.
Se quiseres, podes copiar a pasta ZendSkeletonApplication mantendo-a intacta e usando-a como base para futuros projetos.


O Eclipse abrirá o projeto com exibindo o arquivo composer.json. Nas abas inferiores (General e composer.json), clique em “composer.json” para exibir o código do arquivo.


Vamos incluir a dependência do DOCTRINE e atualizar o projeto. Observe atentamente as mudanças. O código deverá ficar assim:


Vamos salvar e vamos abrir o prompt de comando, entrar no diretório do projeto e executar o comando COMPOSER UPDATE.


O resultado deverá ser igual a esse:

C:\Users\Wagner>cd \xampp\htdocs\temp\ZendSkeletonApplication

C:\xampp\htdocs\temp\ZendSkeletonApplication>composer update
Loading composer repositories with package information
Updating dependencies (including require-dev)
  - Removing zendframework/zendxml (1.0.0)
  - Installing zendframework/zendxml (1.0.1)
    Loading from cache

  - Removing zendframework/zend-stdlib (2.5.1)
  - Installing zendframework/zend-stdlib (2.5.2)
    Loading from cache

  - Removing zendframework/zend-eventmanager (2.5.1)
  - Installing zendframework/zend-eventmanager (2.5.2)
    Loading from cache

  - Removing zendframework/zend-code (2.5.1)
  - Installing zendframework/zend-code (2.5.2)
    Loading from cache

  - Removing zendframework/zend-validator (2.5.1)
  - Installing zendframework/zend-validator (2.5.3)
    Downloading: 100%

  - Removing zendframework/zend-http (2.5.1)
  - Installing zendframework/zend-http (2.5.3)
    Downloading: 100%

  - Removing zendframework/zend-view (2.5.1)
  - Installing zendframework/zend-view (2.5.2)
    Loading from cache

  - Removing zendframework/zend-json (2.5.1)
  - Installing zendframework/zend-json (2.5.2)
    Loading from cache

  - Removing zendframework/zend-inputfilter (2.5.1)
  - Installing zendframework/zend-inputfilter (2.5.5)
    Downloading: 100%

  - Removing zendframework/zend-form (2.5.1)
  - Installing zendframework/zend-form (2.5.3)
    Downloading: 100%

  - Removing zendframework/zend-mvc (2.5.1)
  - Installing zendframework/zend-mvc (2.5.3)
    Downloading: 100%

  - Removing symfony/yaml (v2.7.0)
  - Installing symfony/yaml (v2.7.5)
    Downloading: 100%

  - Removing sebastian/version (1.0.5)
  - Installing sebastian/version (1.0.6)
    Loading from cache

  - Removing sebastian/recursion-context (1.0.0)
  - Installing sebastian/recursion-context (1.0.1)
    Loading from cache

  - Removing sebastian/exporter (1.2.0)
  - Installing sebastian/exporter (1.2.1)
    Loading from cache

  - Removing sebastian/environment (1.2.2)
  - Installing sebastian/environment (1.3.2)
    Loading from cache

  - Removing sebastian/comparator (1.1.1)
  - Installing sebastian/comparator (1.2.0)
    Loading from cache

  - Removing phpunit/php-text-template (1.2.0)
  - Installing phpunit/php-text-template (1.2.1)
    Loading from cache

  - Removing doctrine/instantiator (1.0.4)
  - Installing doctrine/instantiator (1.0.5)
    Loading from cache

  - Removing phpunit/phpunit-mock-objects (2.3.3)
  - Installing phpunit/phpunit-mock-objects (2.3.7)
    Loading from cache

  - Removing phpunit/php-timer (1.0.5)
  - Installing phpunit/php-timer (1.0.7)
    Loading from cache

  - Removing phpunit/php-file-iterator (1.4.0)
  - Installing phpunit/php-file-iterator (1.4.1)
    Loading from cache

  - Removing phpunit/php-token-stream (1.4.1)
  - Installing phpunit/php-token-stream (1.4.8)
    Downloading: 100%

  - Removing phpunit/php-code-coverage (2.1.5)
  - Installing phpunit/php-code-coverage (2.2.3)
    Downloading: 100%

  - Removing phpspec/prophecy (v1.4.1)
  - Installing phpspec/prophecy (v1.5.0)
    Loading from cache

  - Removing phpunit/phpunit (4.7.2)
  - Installing phpunit/phpunit (4.8.9)
    Downloading: 100%

  - Removing zendframework/zend-session (2.5.1)
  - Installing zendframework/zend-session (2.5.2)
    Loading from cache

  - Removing zendframework/zend-modulemanager (2.5.1)
  - Installing zendframework/zend-modulemanager (2.5.3)
    Downloading: 100%

  - Removing zendframework/zend-mail (2.5.1)
  - Installing zendframework/zend-mail (2.5.2)
    Downloading: 100%

  - Removing zendframework/zend-log (2.5.1)
  - Installing zendframework/zend-log (2.5.2)
    Loading from cache

  - Removing zendframework/zend-i18n-resources (2.5.1)
  - Installing zendframework/zend-i18n-resources (2.5.2)
    Loading from cache

  - Removing zendframework/zend-feed (2.5.1)
  - Installing zendframework/zend-feed (2.5.2)
    Loading from cache

  - Removing zendframework/zend-db (2.5.1)
  - Installing zendframework/zend-db (2.5.2)
    Downloading: 100%

  - Removing zendframework/zend-cache (2.5.1)
  - Installing zendframework/zend-cache (2.5.3)
    Downloading: 100%

  - Removing zendframework/zend-barcode (2.5.1)
  - Installing zendframework/zend-barcode (2.5.2)
    Loading from cache

  - Removing zendframework/zend-authentication (2.5.1)
  - Installing zendframework/zend-authentication (2.5.2)
    Loading from cache

  - Removing zendframework/zendframework (2.5.1)
  - Installing zendframework/zendframework (2.5.2)
    Loading from cache

  - Installing psr/http-message (1.0)
    Loading from cache

  - Installing zendframework/zend-diactoros (1.1.3)
    Loading from cache

  - Installing symfony/console (v2.7.5)
    Downloading: 100%

  - Installing doctrine/cache (v1.4.2)
    Downloading: 100%

  - Installing doctrine/lexer (v1.0.1)
    Loading from cache

  - Installing doctrine/annotations (v1.2.7)
    Downloading: 100%

  - Installing doctrine/collections (v1.3.0)
    Loading from cache

  - Installing doctrine/inflector (v1.0.1)
    Loading from cache

  - Installing doctrine/common (v2.5.1)
    Downloading: 100%

  - Installing doctrine/dbal (v2.5.2)
    Downloading: 100%

  - Installing doctrine/orm (v2.5.1)
    Downloading: 100%

symfony/console suggests installing symfony/event-dispatcher ()
symfony/console suggests installing symfony/process ()
symfony/console suggests installing psr/log (For using the console logger)
Writing lock file
Generating autoload files

C:\xampp\htdocs\temp\ZendSkeletonApplication>


Pronto! As dependências estão instaladas e agora só precisamos configurar. Antes de mais nada vamos abrir o navegador e acessar o projeto para ver se está tudo bem.


O Framework Zend é baseado em módulos. Ele vem, a princípio, com um módulo básico chamado Application. Podemos usar esse módulo como base para a criação de outros módulos, ou seja, vamos copiar essa pasta inteira e colar no mesmo diretório, no caso module, com outro nome. Por exemplos, se tivermos em nossa aplicação um controle de usuários (cadastro, alteração, exclusão e leitura) podemos chamar esse módulo de USUARIO.
Clique com o botão direito no módulo Application e escolha COPY, ou pelo teclado apertando CTRL+C, clique no pacote MODULE (logo acima do módulo Application) e cole. Teremos um conflito de nomes. Digite Usuario e confirme.


Vamos registrar esse módulo que acabamos de criar para que ele possa ser enxergado pela nossa aplicação? Abra o arquivo \config\application.config.php e inclua o módulo que criamos. O arquivo ficará assim:


Quando registramos um módulo, o framework busca pelo arquivo Module.php dentro de cada módulo aqui descrito para poder carregar a configuração específica de cada módulo.
Já sabemos que o arquivo Module.php, dentro de cada módulo, descreve a configuração do respectivo módulo no carregamento da aplicação. Podemos, por exemplo, não querer usar o Doctrine em um dado módulo.
Vamos abrir esse arquivo, dentro do módulo que acabamos de criar, e informar que queremos usar o Doctrine. O Doctrine é responsável por fazer a abstração com o nosso banco de dados.
Vamos fazer os imports, definir uma constante, ajustar o método onBootstrap e criar mais 2 métodos. Ajustaremos para que fique da seguinte forma:



Vamos alterar o método getAutoloaderConfig() para que fique assim e vamos criar esses dois métodos:
initializeDoctrine2($e)
getDoctrine2Config($e)


Segue o código do arquivo na íntegra:

<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/ZendSkeletonApplication for the canonical source repository
 * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Usuario;

use Doctrine\Common\Annotations\AnnotationReader;
use Doctrine\Common\Annotations\AnnotationRegistry;
use Doctrine\Common\Cache\ArrayCache;
use Doctrine\ORM\Configuration;
use Doctrine\ORM\EntityManager;
use Doctrine\ORM\Mapping\Driver\AnnotationDriver;
use Zend\Mvc\ModuleRouteListener;
use Zend\Mvc\MvcEvent;
use Zend\I18n\Translator\Translator;
use Zend\Validator\AbstractValidator;

class Module
{
const DOCTRINE_BASE_PATH = '/../../vendor/doctrine/orm/lib/Doctrine';
    public function onBootstrap(MvcEvent $e)
    {
    $e->getApplication()->getServiceManager()->get('translator');
        $eventManager        = $e->getApplication()->getEventManager();
        $moduleRouteListener = new ModuleRouteListener();
        $moduleRouteListener->attach($eventManager);
        $translationPath = realpath(__DIR__ . '/../../vendor/zendframework/zendframework/resources/languages');
        $translator = new Translator();
        $translator->addTranslationFile('phpArray', $translationPath . '/pt_BR/Zend_Validate.php', 'default', 'pt_BR');
        AbstractValidator::setDefaultTranslator(new \Zend\Mvc\I18n\Translator($translator));
        $GLOBALS['sm'] = $e->getApplication()->getServiceManager();
        $this->initializeDoctrine2($e);
    }

    public function getConfig()
    {
        return include __DIR__ . '/config/module.config.php';
    }

    public function getAutoloaderConfig()
    {
        return array(
            'Zend\Loader\StandardAutoloader' => array(
                'namespaces' => array(
                    __NAMESPACE__ => __DIR__ . '/src/' . __NAMESPACE__,
                'Doctrine\Common' => realpath(__DIR__ . self::DOCTRINE_BASE_PATH . '/Common'),
                'Doctrine\DBAL' => realpath(__DIR__ . self::DOCTRINE_BASE_PATH . '/DBAL'),
                'Doctrine\ORM' => realpath(__DIR__ . self::DOCTRINE_BASE_PATH . '/ORM')
                ),
            ),
        );
    }
    
    public function initializeDoctrine2($e) {
    $conn = $this->getDoctrine2Config($e);
    $config = new Configuration();
    $cache = new ArrayCache();
    $config->setMetadataCacheImpl($cache);
    $annotationPath = realpath(__DIR__ . self::DOCTRINE_BASE_PATH . '/ORM/Mapping/Driver/DoctrineAnnotations.php');
    AnnotationRegistry::registerFile($annotationPath);
    $driver = new AnnotationDriver(
    new AnnotationReader(),
    array(__DIR__ . '/src/Cadastro/Model')
    );
    $config->setMetadataDriverImpl($driver);
    $config->setProxyDir(__DIR__ . '/src/Cadastro/Proxy');
    $config->setProxyNamespace('Cadastro\Proxy');
    $entityManager = EntityManager::create($conn, $config);
    $GLOBALS['entityManager'] = $entityManager;
    }
    
    private function getDoctrine2Config($e) {
    $config = $e->getApplication()->getConfig();
    return $config['doctrine_config'];
    }
}

Fim do arquivo

Observe a linha 79 acima. Está vendo a chave doctrine_config? A variável $config contém os dados que são globais em toda a aplicação. Vamos criar esse identificador no arquivo global.php, que fica na raiz da aplicação, com as configurações de conexão com o banco.
Abra o arquivo global.php que está na pasta config\autoload\global.php.

Edite para que fique assim:


Ou seja: Temos aqui a configuração do nosso futuro banco de dados chamado “teste” e o nome de usuário e senha para conexão com o MySql.
Pronto! Nossa aplicação está com o Doctrine configurado e pronto para conexão com o banco de dados.