Tableless

Busca Menu

Iniciando com Symfony 2 – Parte 03

Seja o primeiro a comentar por

Dando continuidade ao tutorial anterior, vamos continuar usando o componente console do Symfony, agora criaremos uma entidade, para acessar o banco de dados, usando o Doctrine ORM.

Banco de dados com Doctrine ORM

Quando falamos de banco de dados em projetos com Symfony, estamos falando de Doctrine ORM (Object Relational Mapper), onde criamos uma camada de persistência entre a aplicação e um banco de dados, que mapeia nossas tabelas com entidades, para que possamos acessar o banco.

Não vou me aprofundar sobre Doctrine, porém, o que você precisa saber é que o Doctrine é um projeto espetacular e grandioso, muito usado pela comunidade, para projetos robustos.

Iniciando com Doctrine ORM

O Doctrine já vem instalado e configurado no Symfony. Lembrando que você pode instalá-lo separadamente via Composer. No primeiro post que escrevi sobre a instalação do Symfony, nós configuramos as opções de banco de dados, o host, usuário e senha. Vale lembrar que são de configuração pessoais, configuradas em sua máquina.
No meu caso, configurei de acordo com minhas configurações do MySQL. Também demos um nome para o banco de dados que vamos utilizar agora e que foi configurado com o nome “symfony”. Porém este não está criado, vamos criá-lo neste momento usando o componente console do Symfony em conjunto com o Doctrine.

Vamos digitar no terminal para criar nosso banco:

$ php app/console doctrine:database:create

E obteremos a resposta: Banco de dados criado para a conexão, com o nome ‘symfony’.

$ Created database for connection named 'symfony'

Gerando Entidades

Agora que nosso banco foi gerado, vamos iniciar criando uma entidade. No Doctrine são objetos leves que contêm propriedades persistentes, que são salvos e recuperados do banco de dados por recursos de mapeamento de dados.

Para gerarmos uma entidade vamos digitar no terminal:

$ php app/console generate:doctrine:entity

Neste momento o console nos dá a dica do que devemos fazer:

“Em primeiro lugar, você precisa dar o nome para a entidade que pretende gerar.
Você deve usar a notação de atalho como AcmeBlogBundle:Post.”

Em nosso caso vamos digitar “TablelessModelBundle:Post”, para criar a entidade Post no bundle TablelessModelBundle.

$ TablelessModelBundle:Post

Feito isso, o console nos pergunda: Qual o formato que vamos usar para obter as informações de mapeamento? Por padrão ele nos indica annotation, vamos deixar como está e damos enter.

$ Configuration format (yml, xml, php, or annotation) [annotation]:

As annotations são usadas pelo Doctrine para mapear as entidades, e obter informações por meio delas.

Após darmos o enter, o console nos indica a inserir novos campos, (Obs: automaticamente, já foi gerado o “id” como primary key), e nos pergunta qual o nome do novo campo que vamos criar:

$ New field name (press  to stop adding fields):

Você pode interromper, apenas dando um enter, em nosso caso vamos continuar, digitando o nosso primeiro campo que será “title”, o titulo de nosso post, damos enter.

$ New field name (press  to stop adding fields):title

Nos pergunta qual o tipo, que vamos usar nesse campo, e ele nos indica “string”, vamos deixar como está, apenas damos um enter.

$ Field type [string]:

A próxima pergunta é: Qual o comprimento desse campo? E por padrão nos indica “255”, você pode deixar assim, em nosso caso vamos digitar “150”, como é um título, para esse projeto não vejo necessidade de mais, damos enter.

$ Field length [255]:150

Criamos nosso primeiro campo na entidade, como é um post, vamos precisar além do titulo, um conteúdo, quando o post foi criado, e quando foi atualizado, então vamos criar nosso próximo campo, digitamos “content”.

$ New field name (press  to stop adding fields): content

O tipo deste campo será um texto, digitamos “text”.

$ Field type [string]:text

Automaticamente, o console não nos pede o tamanho, pois é um campo do tipo text. Vamos para o nosso próximo campo, por convenção digitamos createdAt.

$ New field name (press  to stop adding fields): createdAt

O tipo será uma data, então digitamos “datetime”.

$ Field type [string]: datetime

Vamos para o próximo campo. Nosso post, pode ser atualizado, e para sabermos qual foi a data de atualização vamos criar um campo para isso, digitamos “updatedAt”, também com o tipo “datetime”.

$ New field name (press  to stop adding fields): updatedAt

Tipo

$ Field type [string]: datetime

Como vamos criar um simples blog, e não vamos fazer nada complexo, deixaremos somente estes campos, você pode criar mais campos como texto de introdução, etc, nesse momento vamos deixar assim, e quando o console nos perguntar novamente sobre um novo campo, não vamos digitar nada, apena vamos dar um enter, para entrarmos no processo de finalização.

$ New field name (press  to stop adding fields):

Após o enter, ele nos pergunta se queremos criar uma classe de repositório vazia para a nossa entidade Post, e por padrão, nos indica [não], no momento não vamos usar repositórios, abordaremos isso mais pra frente, novamente damos enter.

$ Do you want to generate an empty repository class [no]?

Nesse momento o console nos pergunta, se confirmamos a geração da nossa entidade, por padrão ele nos indica [Sim], como queremos, damos enter.

$ Do you confirm generation [yes]? 

Pronto, nossa primeira entidade está criada!
Ao entrarmos em nosso projeto, notaremos que uma pasta “Entity” foi criada, e nela teremos nossa entidade “Post”.

Criando entidades no symfony

Nossa entidade Post criada:

<?php

namespace Tableless\ModelBundle\Entity;

use Doctrine\ORM\Mapping as ORM;

/**
 * Post
 *
 * @ORM\Table()
 * @ORM\Entity
 */
class Post
{
    /**
     * @var integer
     *
     * @ORM\Column(name="id", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    private $id;

    /**
     * @var string
     *
     * @ORM\Column(name="title", type="string", length=255)
     */
    private $title;

    /**
     * @var string
     *
     * @ORM\Column(name="content", type="text")
     */
    private $content;

    /**
     * @var \DateTime
     *
     * @ORM\Column(name="createdAt", type="datetime")
     */
    private $createdAt;

    /**
     * @var \DateTime
     *
     * @ORM\Column(name="updatedAt", type="datetime")
     */
    private $updatedAt;


    /**
     * Get id
     *
     * @return integer 
     */
    public function getId()
    {
        return $this->id;
    }

    /**
     * Set title
     *
     * @param string $title
     * @return Post
     */
    public function setTitle($title)
    {
        $this->title = $title;

        return $this;
    }

    /**
     * Get title
     *
     * @return string 
     */
    public function getTitle()
    {
        return $this->title;
    }

    /**
     * Set content
     *
     * @param string $content
     * @return Post
     */
    public function setContent($content)
    {
        $this->content = $content;

        return $this;
    }

    /**
     * Get content
     *
     * @return string 
     */
    public function getContent()
    {
        return $this->content;
    }

    /**
     * Set createdAt
     *
     * @param \DateTime $createdAt
     * @return Post
     */
    public function setCreatedAt($createdAt)
    {
        $this->createdAt = $createdAt;

        return $this;
    }

    /**
     * Get createdAt
     *
     * @return \DateTime 
     */
    public function getCreatedAt()
    {
        return $this->createdAt;
    }

    /**
     * Set updatedAt
     *
     * @param \DateTime $updatedAt
     * @return Post
     */
    public function setUpdatedAt($updatedAt)
    {
        $this->updatedAt = $updatedAt;

        return $this;
    }

    /**
     * Get updatedAt
     *
     * @return \DateTime 
     */
    public function getUpdatedAt()
    {
        return $this->updatedAt;
    }
}

Configurando a entidade

Vamos fazer algumas modificações.
Daremos o nome “post” pra nossa tabela quando ela for criada, para isso temos que configurar via annotation para que o Doctrine saiba. Para fazer isso vamos adicionar na linha 10 a annotation correspondente:
Obs: As annotations do Doctrine, começam com “@ORM\”, o restante é documentação…
Verifique a alteração na linha 10, vamos inserir: (name=”post”).
Caso não façamos essa alteração, não ocorrerá erro, porém por padrão o Doctrine criará uma tabela com o nome da classe “Post”, com a letra “P” maiúscula.

/**
 * Post
 *
 * @ORM\Table(name="post")
 * @ORM\Entity
 */
class Post
{
...

Mudaremos também o nome da coluna “createdAt” para “creadet_at” na linha 41 de nossa entidade, no caso do código abaixo, a linha 4.

/**
 * @var \DateTime
 *
 * @ORM\Column(name="created_at", type="datetime")
 */
 private $createdAt;
...

E a linha 48, de “updatedAt” para “updated_at”, no código abaixo a linha 4.

/**
 * @var \DateTime
 *
 * @ORM\Column(name="updated_at", type="datetime")
 */
 private $updatedAt;
...

Precisamos que, ao criarmos nosso post, seja inserido automaticamente a data de criação, e a data de atualização, para isso vamos criar um método construtor em nossa entidade, veja abaixo:

/**
 * Construct
 */
 public function __construct()
 {
    $this->createdAt = new \DateTime();
    $this->updatedAt = new \DateTime();
 }

Validando

Agora vamos fazer uma validação, para que nossos campos “title” e “content”, não aceitem conteúdos nulos, em brancos. Para isso chamaremos a classe Constraints do Symfony, dando um “use” nesse objeto em nossa entidade, por padrão daremos o apelido de Assert para Constraints. Veja na linha 06:

<?php

namespace Tableless\ModelBundle\Entity;

use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;

/**
 * Post
 *
 * @ORM\Table(name="post")
 * @ORM\Entity
 */
class Post
{

Para que a validação seja feita colocaremos a annotation “@Assert\NotBlank” nos campos que queremos, veja na linha 5 e na linha 13:

/**
 * @var string
 *
 * @ORM\Column(name="title", type="string", length=255)
 * @Assert\NotBlank
 */
 private $title;

 /**
 * @var string
 *
 * @ORM\Column(name="content", type="text")
 * @Assert\NotBlank
 */
 private $content;

Pronto! Nossa entidade Post está criada e configurada, porém faremos modificações no fututo para que ela se adeque melhor em nosso projeto.

Gerando CRUD com Doctrine ORM

Agora que nossa entidade está concluída, vamos fazer um CRUD, para que possamos inserir, atualizar, visualizar e deletar nossos posts.
Porém antes, precisamos criar nossas tabelas, para fazer isso, vamos voltar para o terminal e digitar:

$ php app/console doctrine:schema:create

Receberemos a resposta do console:
“ATENÇÃO: Esta operação não deve ser executado em um ambiente de produção.
Criação de esquema de banco de dados…
Esquema de banco de dados criado com sucesso!”

ATTENTION: This operation should not be executed in a production environment.

Creating database schema...
Database schema created successfully!

Vamos ao CRUD! Para fazer um CRUD com Doctrine, é extremamente fácil, vamos digitar no terminal:

$ php app/console generate:doctrine:crud

Ao digitarmos o comando acima e darmos o enter, entramos no assistente para criarmos nosso CRUD, e ele nos pede para que informemos a entidade que queremos criar o CRUD, então digitamos: TablelessModelBundle:Post

$ The Entity shortcut name: TablelessModelBundle:Post

Logo após, nos pergunta se queremos gerar as ações de “gravação”, ele nos indica [não], porém nós queremos, então digitamos “yes”.

$ Do you want to generate the "write" actions [no]? yes

Nos pergunta como vamos configurar nosso CRUD, e nos indica [annotation], só damos um enter para prosseguir.

$ Configuration format (yml, xml, php, or annotation) [annotation]:

Após o enter, nos pergunta como vai ser a rota que vamos usar, e nos indica [/post], vamos usar essa mesma, damos um enter.

$ Routes prefix [/post]:

Nos pergunta se confirmamos a geração, e nos indica [yes], sim queremos, damos enter para prosseguir.

$ Do you confirm generation [yes]?

Pronto! CRUD criado, simples não!

Nesse momento vamos fazer uma configuração somente para vermos nossa aplicação rodando, porém não vamos usar essa rota, é somente para vermos se está tudo certo. Entre no arquivo app/config/route.yml e vamos adicionar a rota desse CRUD:

tableless_model:
    resource: "@TablelessModelBundle/Controller/"
    type:     annotation
    prefix:   /

Agora vamos rodar nosso aplicação pelo console:

$ php app/console server:run

E vamos entrar no navegador com a url:

http://127.0.0.1:8000/post/

Para inserirmos um novo post, é só dar um clique, em “Create a new entry”.
Eu inseri um post, com um texto “Lorem Ipsum”, apenas para reprodução das páginas, veja o resultado abaixo:

Lista de posts = url: http://127.0.0.1:8000/post/
Novo post = url: http://127.0.0.1:8000/post/new
Ver o post = url: http://127.0.0.1:8000/post/1
Editar post = url: http://127.0.0.1:8000/post/1/edit

Páginas criadas

Ao navegar pelas páginas, verificará, que não tem estilização, porém está funcional, vamos fazer isso mais tarde, poderá verificar também seu banco de dados, e verá que foi criado um banco de dados com o nome “symfony”, nesse banco, encontrará a tabela “post” que criamos.

Table post no banco de dados

Concluindo

Uma observação importante, estamos criando nossos códigos por linha de comando usando o console, é uma forma de mostrar a agilidade e produtividade, que o Symfony e o Doctrine nos permite, porém para entender o mínimo, o funcionamento do Symfony, ou de qualquer outro framework PHP, é de extrema importância saber PHP Orientado a Objetos, padrão MVC e outros Design Patterns. Fazer a reprodução codificando, sem usar o console, é uma boa forma de aprender e entender o funcionamento do Symfony.

Este projeto encontra-se no gitHub.

Publicado no dia