segunda-feira, 17 de setembro de 2012

Paginação com Doctrine e Zend_Framework

Olá amigos, hoje vou mostra basicamente como paginar dados usando o Zend Framework e o Doctrine, inicialmente parece algo complexo, mas vcs vão perceber que é simples.

Se vc ainda não fez uma paginação com o zend framework leia esse meu artigo sobre paginação com o ZF Paginando com Zend Framework e depois corra aqui, ou se preferir fique por aqui mesmo.

Vamos lá, vou mostrar a paginação de forma bem simples pois o grande problema de fazer um artigo sobre paginação do Zend Framework com Doctrine é que isso varia muito a arquitetura que cada um esta usando, mas nesse caso isso não vai atrapalhar pois vc vai adaptar de acordo com a sua arquitetura.

Mãos a obra

No controller....
  exemplo de consulta
  1.  public function exemploAction() {
  2.  
  3.         $request = $this->getRequest();
  4.  
  5.         if ($request->getPost()) {
  6.  
  7.             $params = $request->getPost();
  8.             $pagina = (int) $params['pag'];
  9.  
  10.             $front = \Zend_Controller_Front::getInstance();
  11.             $em = $front->getParam('bootstrap')->getResource('entityManager');
  12.             $dql = $em->createQuery("select a from Entidade_Pessoa a");
  13.  
  14.             $dados = new \DoctrineExtensions\Paginate\PaginationAdapter($dql);
  15.  
  16.             $paginator = new Zend_Paginator($dados);
  17.             // Seta a quantidade de registros por página
  18.             $paginator->setItemCountPerPage(4);
  19.             // numero de paginas que serão exibidas
  20.             $paginator->setPageRange(15);
  21.             // Seta a página atual
  22.             $paginator->setCurrentPageNumber($pagina);
  23.         }
  24.  
  25.  
  26.         $this->view->paginator = $paginator;
  27.  }

Veja que simples, usamos uma paginação aparentemente comum  do ZF não é? mas passamos para o zend_paginador a variavel $dados que contem a instância da PaginationAdapter que recebe a consulta dql e faz toda a brincadeira... esse cara esta aqui abaixo é uma classe que implementa a \Zend_Paginator_Adapter_Interface e por isso o Zend_Paginator sabe trabalhar com o objeto pois os métodos que ele usa são do nome da interface.
Lindo não é?








Veja a classe:

  ADAPTER DO DOCTRINE
  1. /**
  2.  * DoctrineExtensions Paginate
  3.  *
  4.  * LICENSE
  5.  *
  6.  * This source file is subject to the new BSD license that is bundled
  7.  * with this package in the file LICENSE. This license can also be viewed
  8.  * at http://hobodave.com/license.txt
  9.  *
  10.  * @category    DoctrineExtensions
  11.  * @package     DoctrineExtensions\Paginate
  12.  * @author      David Abdemoulaie <dave@hobodave.com>
  13.  * @copyright   Copyright (c) 2010 David Abdemoulaie (http://hobodave.com/)
  14.  * @license     http://hobodave.com/license.txt New BSD License
  15.  */
  16.  
  17. namespace DoctrineExtensions\Paginate;
  18.  
  19. use Doctrine\ORM\Query;
  20.  
  21. /**
  22.  * Implements the Zend_Paginator_Adapter_Interface for use with Zend_Paginator
  23.  *
  24.  * Allows pagination of Doctrine\ORM\Query objects and DQL strings
  25.  *
  26.  * @category    DoctrineExtensions
  27.  * @package     DoctrineExtensions\Paginate
  28.  * @author      David Abdemoulaie <dave@hobodave.com>
  29.  * @copyright   Copyright (c) 2010 David Abdemoulaie (http://hobodave.com/)
  30.  * @license     http://hobodave.com/license.txt New BSD License
  31.  */
  32. class PaginationAdapter implements \Zend_Paginator_Adapter_Interface {
  33.  
  34.     /**
  35.      * The SELECT query to paginate
  36.      *
  37.      * @var Query
  38.      */
  39.     protected $query = null;
  40.  
  41.     /**
  42.      * Total item count
  43.      *
  44.      * @var integer
  45.      */
  46.     protected $rowCount = null;
  47.  
  48.     /**
  49.      * Use Array Result
  50.      *
  51.      * @var boolean
  52.      */
  53.     protected $arrayResult = false;
  54.  
  55.     /**
  56.      * Constructor
  57.      *
  58.      * @param Query $query
  59.      * @param string $ns Namespace to prevent named parameter conflicts
  60.      */
  61.     public function __construct(Query $query) {
  62.  
  63.         $this->query = $query;
  64.  
  65.     }
  66.  
  67.     /**
  68.      * Set use array result flag
  69.      *
  70.      * @param boolean $flag True to use array result
  71.      */
  72.     public function useArrayResult($flag = true) {
  73.         $this->arrayResult = $flag;
  74.     }
  75.  
  76.     /**
  77.      * Sets the total row count for this paginator
  78.      *
  79.      * Can be either an integer, or a Doctrine\ORM\Query object
  80.      * which returns the count
  81.      *
  82.      * @param Query|integer $rowCount
  83.      * @return void
  84.      */
  85.     public function setRowCount($rowCount) {
  86.         if ($rowCount instanceof Query) {
  87.             $this->rowCount = $rowCount->getSingleScalarResult();
  88.         } else if (is_integer($rowCount)) {
  89.             $this->rowCount = $rowCount;
  90.         } else {
  91.             throw new \InvalidArgumentException("Invalid row count");
  92.         }
  93.     }
  94.  
  95.     /**
  96.      * Sets the namespace to be used for named parameters
  97.      *
  98.      * Parameters will be in the format 'namespace_1' ... 'namespace_N'
  99.      *
  100.      * @param string $ns
  101.      * @return void
  102.      * @author David Abdemoulaie
  103.      */
  104.     public function setNamespace($ns) {
  105.         $this->namespace = $ns;
  106.     }
  107.  
  108.     /**
  109.      * Gets the current page of items
  110.      *
  111.      * @param string $offset
  112.      * @param string $itemCountPerPage
  113.      * @return void
  114.      * @author David Abdemoulaie
  115.      */
  116.     public function getItems($offset, $itemCountPerPage) {
  117.  
  118.         $this->query->setFirstResult($offset);
  119.         $this->query->setMaxResults($itemCountPerPage);
  120.         $entities = $this->query->getResult();
  121.  
  122.         return $entities;
  123.     }
  124.  
  125.     /**
  126.      * @param Query $query
  127.      * @return int
  128.      */
  129.     public function count() {
  130.         if (is_null($this->rowCount)) {
  131.             $this->setRowCount(
  132.                     $this->createCountQuery()
  133.             );
  134.         }
  135.         return $this->rowCount;
  136.     }
  137.  
  138.     /**
  139.      * @return Query
  140.      */
  141.     protected function createCountQuery() {
  142.         return Paginate::createCountQuery($this->query);
  143.     }
  144.  
  145.     /**
  146.      * @return Query
  147.      */
  148.     protected function createLimitSubquery($offset, $itemCountPerPage) {
  149.         return Paginate::createLimitSubQuery($this->query, $offset, $itemCountPerPage);
  150.     }
  151.  
  152.     /**
  153.      * @return Query
  154.      */
  155.     protected function createWhereInQuery($ids) {
  156.         return Paginate::createWhereInQuery($this->query, $ids, $this->namespace);
  157.     }
  158.  
  159. }
Veja que nós implementamos os métodos da interface e montamos o resultado então na view é só pegar como de costume o "$this->paginator" iterar ele e mandar bala!



Dúvidas? Me avisem pois fiz esse post meio correndo... rsrs




 

terça-feira, 11 de setembro de 2012

Contando objeto no PHP

... Eis que surge a dúvida, como eu conto os atributos de um objeto? Será que count/sizeof funciona? Vamos testar?

Criando uma classe pessoa com os atributos nome, sexo e idade:
 CLASSE PESSOA
  1. class Pessoa{
  2.    
  3.     private $nome;
  4.     private $sexo;
  5.     private $idade;
  6.    
  7.     public function getNome() {
  8.         return $this->nome;
  9.     }
  10.     public function setNome($nome) {
  11.         $this->nome = $nome;
  12.     }
  13.     public function getSexo() {
  14.         return $this->sexo;
  15.     }
  16.     public function setSexo($sexo) {
  17.         $this->sexo = $sexo;
  18.     }
  19.     public function getIdade() {
  20.         return $this->idade;
  21.     }
  22.     public function setIdade($idade) {
  23.         $this->idade = $idade;
  24.     }
  25.    
  26. }

Vamos criar uma instância dessa classe e popular ela, depois utilizamos o count na busca de um resultado mágico ok?
tentando contar atributos de um objeto
  1. $pv = new Pessoa();
  2. $pv->setNome("Paulo Victor");
  3. $pv->setSexo("M");
  4. $pv->setIdade("23");
  5. echo sizeof($pv);
E ai o que ele vai retornar? Nesse caso retorna 1 pois o objeto é válido e ponto. (If you try to do a sizeof or count with an object, it will always return 1 if the object is not null)

OBS: sizeof é um atalho para a função count


I ai ferro, será que tem algo específico para contar um objeto?






..... Pesquisando e pesquisando descobrimos que a melhor solução nesse caso é fazer um cast do objeto para array, juro, dentro do count isso é lindo, assim como diz na documentação do php veja:
You need to type cast the object as an array for it to count correctly. (fonte: http://www.php.net/manual/en/function.count.php)

Então ficaria assim:

 contaNDO atributos de um objeto
  1. $pv = new Pessoa();
  2. $pv->setNome("Paulo Victor");
  3. $pv->setSexo("M");
  4. $pv->setIdade("23");
  5. echo sizeof((array) $pv); // 3
Pronto, a saída disso será 3, o número de atributos.


Que simples não é? Igual a epoca em que jogavamos Alex kidd(foto, graaande alex kidd)

Pois bem, ai talvez vc me faça uma pergunta(diga-se de passagem, muito inconveniente kkkk) se não existem forma de tornar a contagem mais lógica de objetos, e ai amiguinho eu te dou uma resposta de alto nível que é; O PHP se preparou para tudo(quase tudo) e para esses casos existe a interface ArrayAccess que permite vc manipular objetos como array e array o PHP já tem 321402342034923049203492304 funções.
 Mas, esse é um assunto para o próximo artigo(que eu juro q vou falar sobre). 



Agora se vc quer contar exatamente um atributo e não quer ter muito trabalho eu idico dar uma lida na interface Countable da SPL(uma biblioteca com diversas classe e interfaces para PHP, que vão desde estruturas de dados, implementações de Design patterns, Iterators, Exceptions e funções diversas) aqui no blog do Thiago Rigo tem uma boa explicação sobre ela http://thiagorigo.com/blog/2010/07/spl-countable/

Então é isso. Valeu!



sábado, 8 de setembro de 2012

PHP como CGI ou como módulo de Apache

A diferença do PHP como CGI do apache é que ele é configurado como um "assistente" e assim é menos propício à problemas, porém menos seguro tb.

Já o PHP como módulo do apache, vira uma extensão do WebSever(no caso apache), habilitando mais opções, módulos e etc, é mais seguro, porém o risco de problemas é maior.



Basicamente a diferença é Speed and Power, os sites normalmente instalam o PHP como modulo do webserver (Apache, Nginx...)

Mais:

Installed as CGI binary [ca.php.net
Installed as an Apache module [ca.php.net]

terça-feira, 4 de setembro de 2012

Removendo dd e dt Zend_Form

Eu tenho esse HTML defaul do Zend_Form como faço para resolver?
1
2
<dt id="MyElement-label">&nbsp;</dt>
Usando o metodo removeDecorator assim:
1
2
3
4
5
$id = $form->createElement('hidden', 'id');
$id->removeDecorator('DtDdWrapper');
$id->removeDecorator('HtmlTag');
$id->removeDecorator('Label');
$form->addElement($id);
Resultado:
1
<input type="hidden" name="MyElement" value="something" id="MyElement">
FUI