Mostrando postagens com marcador doctrine. Mostrar todas as postagens
Mostrando postagens com marcador doctrine. Mostrar todas as postagens

terça-feira, 20 de novembro de 2012

Annotations no Doctrine - @Column

Nesse post vou falar um pouco sobre as Annotations no Doctrine buscando deixar essa página como guia de consulta rápida para vc escrever suas entidades ok?

O que vc precisa saber para entender esse artigo:
  • Lógica de programação
  • PHP
  • POO
  • ORM
  • Conhecer pelo menos o básico de Doctrine


Bem, o que são essas annotations? Para quem conhece Java sabe que é indiscutível a agilidade e facilidade de configuração que as annotations proporcionam, elas são formas de descrever toda uma classe através de comentários.

Com o objetivo de trazer tal comodidade ao PHP surgiu o projeto Addendum – escrito por Jan Suchal – que permite via Reflection acessar as annotations das classes.
As annotations devem ser escritas em blocos de comentários, uma vez que o @ (caracter que inicia uma annotation) é um caractere reservado no PHP. Elas podem ser mono ou multi valoradas de acordo com os exemplos abaixo.


  1. // Custom annotation  
  2. class Persistent extends Annotation {}  
  3. // Custom annotation  
  4. class Table extends Annotation {}  
  5. // Multi valued annotation  
  6. class Secured extends Annotation {  
  7.    public $role;  
  8.    public $level;  
  9. }  
  10. /**  
  11.  * @Persistent  
  12.  * @Table("people")
  13.  * @Secured(role = "admin", level = 2)
  14.  */  
  15. class Person {  
  16.    // some code  
  17. }  
  18. // getting the annotation by class name  
  19. $reflection = new ReflectionAnnotatedClass('Person');  
  20. // getting the annotation by instance  
  21. $person = new Person();  
  22. $reflection = new ReflectionAnnotatedClass($person);  
  23. // true  
  24. $reflection->hasAnnotation('Persistent');  
  25. // contains string "people"  
  26. $reflection->getAnnotation('Table')->value;


No doctrine usamos as annotations para descrever uma classe que representa uma entidade do sistema ou seja, uma tabela no banco, seguindo a mesma onda da JPA, facilitando a configuração das classes de persistência e seus relacionamentos.



  1. /**
  2.  * @DoctrineEntity(tableName="pessoa")
  3.  */  
  4. class Pessoa {  
  5.    /**
  6.     * @DoctrineId
  7.     * @DoctrineColumn(type="integer")
  8.     * @DoctrineIdGenerator("auto")
  9.     */  
  10.    public $id;  
  11.    /**
  12.     * @DoctrineColumn(type="varchar", length=255)
  13.     */  
  14.    public $nome;  
  15.    /**
  16.     * @DoctrineColumn(type="varchar")
  17.     */  
  18.    public $sobrenome;  
  19.    /**
  20.     * @DoctrineManyToOne(targetEntity="Usuario",
  21.            joinColumns={"user_id" = "id"})
  22.     */  
  23.    public $usuario;  
  24.    
  25. }



Vejam que acabamos de criar uma entidade pessoa onde apontamos os campos e os tipos dos campos, no ultimo uma outra entidade(usuario) montando o relacionamento ManyToOne.



Bem eu precisei dar essa parte básica do Doctrine para finalmente montarmos uma relação das annotations então, chega de enrolar.




Annotations Doctrine

@Column (O mais utilizado, e o mais básico)
Esse é o carinha que define a maioria das colunas que criamos dentro de nossas entidades, o proprio nome diz, é ele que marca um atributo como uma coluna válida no banco. Qualquer espera de valor dentro desta variável será salvo e carregado a partir do banco de dados como parte do ciclo de vida das variáveis ​​de instância da entidade de classe.



Atributos requeridos:
  • type: Tipo do atributo para que seja criado a coluna no banco baseado nesse tipo como por exemplo char, int etc...
Atributos opcionais:
  • name: Por padrão o nome do atributo é o nome da coluna no banco(sem o $ é claro), mas pe possível determinar um outro nome para a coluna utilizando o name.
  • length: Usado para tipo "string" serve para determinar o limite máximo de caracteres dessa coluna. O Doctrine não valida o tamanho da string no funcionamento do sistema, oque aconteceria era um funcionamento comum onde apenas o limite liberado é que seria gravado no banco de dados.
  • precision: Marca a precisão de números decimais(número exato) da coluna (Aplicado apenas para colunas decimais)
  • scale: The scale for a decimal (exact numeric) column (Applies only for decimal column)
  • unique: Valor booleano que determina se o valo é unico.
  • nullable: Determina se coluna pode ser NULL.
  • columnDefinition:  DDL SQL trecho que se inicia após o nome da coluna e especifica a definição de coluna completa (non-portable!). Este atributo permite fazer uso de recursos avançados RMDBS. No entanto, você deve fazer uso cuidadoso deste recurso tomando cuidado com as conseqüências. SchemaTool não irá detectar alterações na coluna mais correctamente se você usar "ColumnDefinition".
    Além disso, você deve se lembrar que o "type" ainda lida com a conversão entre PHP e os valores do banco de dados. Se você usar esse atributo em uma coluna que é usada para junções entre tabelas você também deve dar uma olhada em @ JoinColumn.


Exemplos simples:

  1. <?php
  2. namespace GuestBook\Model\Doctrine\Entity;
  3. /**
  4.  *
  5.  * @Table(name="guestbook")
  6.  * @Entity
  7.  */
  8. class GuestBookDoctrine{
  9.    
  10.     /**
  11.      * @var integer $id
  12.      * @Column(type="integer")
  13.      * @Id
  14.      * @GeneratedValue(strategy="IDENTITY")
  15.      */
  16.     private $id;
  17.    
  18.     public function setId($id){$this->id = $id;}
  19.     public function getId(){return $this->id;}
  20.    
  21.    
  22.     /**
  23.      * @Column(type="string", length="100")
  24.      */
  25.     private $title;
  26.     public function setTitle($title){$this->title=$title;}
  27.     public function getTitle(){return $this->title;}
  28.    
  29. }



Exemplo da documentação do doctrine:
<?php
/**
 * @Column(type="string", length=32, unique=true, nullable=false)
 */
protected $username;

/**
 * @Column(type="string", columnDefinition="CHAR(2) NOT NULL")
 */
protected $country;

/**
 * @Column(type="decimal", precision=2, scale=1)
 */
protected $height;




Bem acho que por hoje é só, até o próximo artigo sobre mais annotations do doctrine.


domingo, 21 de outubro de 2012

Utilizando o LIKE no Doctrine

Quer utilizar o LIKE com Doctrine? Essa é simples!

SIMMMMMMMMMMMMMMMMMM



Esse não é nem um artigo mas sim uma dica/lembrança para consulta rápida...




Utilizando QueryBuilder
<?php
// $qb instancia de QueryBuilder

$qb->select(array('u')) // string 'u' is converted to array internally
   ->from('User', 'u')
   ->where($qb->expr()->orX(
       $qb->expr()->eq('u.id', '?1'),
       $qb->expr()->like('u.nickname', '?2')
   ))
   ->orderBy('u.surname', 'ASC'));



E Utilizando DQL

<?php
$query = $em->createQuery("SELECT u FROM CmsUser u LEFT JOIN u.articles a WITH a.topic LIKE :foo");
$query->setParameter('foo', '%foo%');
$users = $query->getResult();



Bem, é isso rsrs... 

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