Olá pessoal!
No último artigo, aprendemos a configurar a aplicação e trabalhar com componentes e parciais. Hoje veremos como trabalhar com dados. Vamos criar o banco de dados do nosso projeto e exibir estes dados e/ou informações, conforme nossa necessidade.
Symfony trabalha com uma abstração de dados bem simples de se configurar. Aliás, a mais simples que eu já vi. Se usar Doctrine, que é uma poderosa ORM, fica tudo ainda mais fácil. É claro que, as vezes, há de se fazer ligações ou relacionamentos bastante complexos. Então, fica evidente a necessidade de utilizarmos uma ORM que tenha bastante documentação.
Já utilizei muito a ORM Propel, entretanto, nada se compara a ORM Doctrine!
Criando o modelo relacional do nosso projeto
Para manipularmos dados temos que fazer algo simples, mas muito importante para o desenrolar de qualquer projeto. Neste caso usei o DBDesigner que é uma ferramenta bem simples e nos possibilita criar as entidades e relacioná-las conforme o seu modelo. Veja o modelo ER do nosso projeto:
Bem, você poderá fazer desta forma. Modelar os dados usando softwares como DBDesigner ou Workbench assim que você tiver uma expecificação do projeto. Entretanto, suponha que você não tem toda as regras de negócio do projeto. Neste caso, ficará faltando entidades e relacionamentos. Para suprir essa carência usaremos o lançamento das informações que o próprio symfony dispõe. Vamos configurar um banco de dados sabendo que podemos fazer alterações a qualquer momento depois de pronto o projeto.
Definindo o Schema pelo Symfony
Criaremos, primeiramente, a base de dados pelo terminal do Ubuntu. Navegaremos até a base de dados do nosso projeto, ou seja, o projeto ‘imasters’ e a base também levará este mesmo nome. Abrimos o terminal (com permissão de ‘sudo su’) e digitaremos o seguinte:
$ mysqladmin -uroot -p create imasters
Uma solicitação de senha do banco de dados aparecerá no seu terminal, linha inferior. Digite a senha que você definiu quando instalou e configurou o seu banco de dados. Se você não fez isso ainda, veja isso aqui. Feito isso, você poderá visualizar o banco ‘imasters’ criado na sua base, pelo phpmyadmin ou qualquer outra ferramenta que você utiliza para manipular seus bancos de dados locais.
Configurando o acesso ao Banco de Dados MySQL
Vamos abir o arquivo ‘databases.yml’ para configurar a conexão:
#/imasters/config/databases.yml
all:
doctrine:
class: sfDoctrineDatabase
param:
dsn: mysql:host=localhost;dbname=imasters
username: root
password: root
Você apenas vai ter que inserir o texto em vermelho, caso já não esteja informado:
Definindo as tabelas e fazendo os relacionamentos
Agora vamos criar o banco propriamente, utilizando o arquivo ‘schema.yml’. Definiremos todo o nosso schema, porém, isso não impede de eu alterar futuramente:
#/imasters/config/doctrine/schema.yml
Categoria:
actAs:
Timestampable: ~
Sluggable: { fields: [nome], unique: true }
columns:
nome: { type: string(32), notnull: true }
is_public: { type: boolean, notnull: true, default: 1 }
Conteudo:
actAs:
Timestampable: ~
Sluggable: { fields: [titulo], unique: true }
columns:
categoria_id: { type: integer, notnull: true }
titulo: { type: string(255), notnull: true }
resumo: { type: string(500) }
conteudo: { type: string(6000), notnull: true }
is_public: { type: boolean, notnull: true, default: 1 }
relations:
Categoria: { onDelete: CASCADE, local: categoria_id, foreign: id, foreignAlias: Conteudos }
Galeria:
actAs:
Timestampable: ~
columns:
nome: { type: string(200), notnull: true }
arquivo: { type: string(200), notnull: true }
descricao: { type: string(600) }
is_public: { type: boolean, notnull: true, default: 1 }
Noticia:
actAs:
Timestampable: ~
Sluggable: { fields: [titulo], unique: true }
columns:
titulo: { type: string(255), notnull: true }
conteudo: { type: string(6000), notnull: true }
is_public: { type: boolean, notnull: true, default: 1 }
Autorizacao:
actAs:
Timestampable: ~
columns:
is_public: { type: boolean, notnull: true, default: 0 }
relations:
Noticias:
class: Noticia
refClass: NoticiaAutorizacao
local: autorizacao_id
foreign: noticia_id
foreignAlias: Autorizacoes
NoticiaAutorizacao:
columns:
noticia_id: { type: integer, primary: true }
autorizacao_id: { type: integer, primary: true }
relations:
Noticia: { onDelete: CASCADE, local: noticia_id, foreign: id }
Autorizacao: { onDelete: CASCADE, local: autorizacao_id, foreign: id }
Bem, este é o schema definido. Vejam que eu fiz a mesma coisa que foi feito no desenho acima. Ou seja, meu modelo ER está “desenhado” no symfony e a sua maneira. Para entender melhor visite o site www.doctrine-project.org.
Para aqueles que já trabalham com banco de dados, isso é como “tirar doce de criança”. Para quem não entendeu, sugiro um estudo mais aprofundado em banco de dados (mysql é super fácil).
Já estamos a um passo de concluir. – Olha que barbada!
Criando as Tabelas no Banco e definindo-as como objetos para aplicação
Abra o seu terminal no projeto e digite o comando ‘NINJA’ que, além de criar suas tabelas no banco de dados, criará todos o formulários, os objetos ( classes) e filtros relativo à sua base de dados. Ou seja, TODO o modelo de dados será definido em apenas um comando.
$ php symfony doctrine:build --all
Ao executar o comando ele vai perguntar ‘se você tem certeza que deseja limpar todos os dados’. Ou seja, CUIDADO! Suponha que você tem dados gravados no banco de dados e se você executar este comando, vai LIMPAR o seu banco de dados. Porque este comando exclui o banco e cria-o novamente. No nosso caso, pressione a letra y e após tecle ENTER:
Após uma série de linhas listadas no seu terminal ele informará que ‘criou as tabelas com sucesso’. Para conferir abra o seu navegar e digite http://localhost/phpmyadmin e verá algo assim:
Fácil, mas temos algumas coisa importantes para definirmos: Como já sabemos quais são os itens do menu, iremos então cadastrá-los permanente ao projeto. Estou fazendo isso, sabendo que poderei modificar meu banco, e aplicar novamente o comando “buil –all” no futuro.
Inserindo dados no banco atráves da linha de comando
O arquivo onde definiremos os dados “permanentes” é chamado de “fixtures.yml” e fica no diretório data:
#/imasters/data/fixtures/fixtures.yml
Categoria:
home:
nome: Home
projeto:
nome: O Projeto
noticia:
nome: Notícias
galeria:
nome: Galeria
contato:
nome: Contato
Após, execute o seguinte comando no seu terminal:
$ php symfony doctrine:data-load
Legal, agora você vai clicar na tabela “categoria” e ver algo assim:
Não esqueça de limpar o cache da aplicação
$ php symfony cc
Botando em Prática
Para ficar bem mais emocionante vamos “buscar” do banco de dados estas informações e construir nosso menu.
Editando o Menu da Aplicação e Manipulando dados
Abriremos a nossa app chamada “frontend” e vamos editar o componente:
//- imasters/apps/frontend/modules/home/actions/
<?php
/******* components.class ********
controlador de componentes
do módulo home
**********************************/
class homeComponents extends sfComponents{
public function executeMenu(sfWebRequest $request){
$c = Doctrine_Query::create()
->from('Categoria c')
->where('c.is_public = ?', true);
$this->menus = $c->fetchArray();
}
}components.class.php
Veja que a consulta me traz os registros da tabela “categoria” onde estão publicados. Quando trabalharmos com o gerenciador de contúdos você verá que tudo ficará mais fácil de entender.
Agora vamos editar a visão do compontente. Não se atrapalhe, acabei de editar o método Menu. Agora vou editar a visão deste método.
//--imasters/apps/frontend/modules/home/templates/_menu.php
<ul>
<?php foreach($menus as $menu): ?>
<li><a href="<?php echo url_for('@'.$menu['slug'])?>"><?php echo $menu['nome'] ?></a></li>
<?php endforeach; ?>
</ul>
Aqui determinamos ações aos menus e tais ações ainda não estão definidas: Vamos identificar e entender os erros do Symfony:
Tratando erros no symfony
Por padão e segurança, o framework não mostra os erros gerados em produção. Somente no modo desenvolvimento é possível o desenvolvedor depurar estes erros e visualizá-los para tratá-los como complemento de correção. Em produção, os erros acontecem conforme a imagem abaixo:
Isso prova que tivemos um Execption no nosso código. Óbvio que já sabemos do que se trata. Então iremos verificar em desenvolvimento para sabermos como fazer isso em outras situações onde não se sabe o que houve. – Ah, para os navegantes, este erro é por causa dos “slugs’ que ainda não estão definidos no arquivo de roteamento, ‘routing.yml’. Visualizando o ambiente de debug do symfony “http://imasters.tut.br/frontend_dev.php“.
Vamos ao tratamento então: Abriremos o arquivo de roteamento e adicionamos o código conforme abaixo:
#imasters/apps/frontend/config/routing.yml
homepage:
url: /
param: { module: home, action: index }
home:
url: /
param: { module: home, action: index }
o-projeto:
url: /projetos.html
param: { module: conteudo, action: index }
noticias:
url: /ultimas_noticias
param: { module: noticia, action: index }
galeria:
url: /galeria-de-imagens
param: { module: galeria, action: index }
contato:
url: /contate-nos
param: { module: contato, action: index }
# generic rules
# please, remove them by adding more specific rules
default_index:
url: /:module
param: { action: index }
default:
url: /:module/:action/*
Veja como é simples fazer o roteamento. Com isso eu defini o que, literalmente, vai ser visualizado no browser (exemplo: a regra ‘o-projeto’ ficou ‘projetos.html’ exibido pelo browser). Ou seja, posso definir o que eu quiser no link.
Aproveitamos para enfatizar que toda vez que for alterado qualquer arquivo .yml é obrigatório a execução da limpeza de cache:
$ php symfony cc
Agora vamos editar a folha de estilo para entendermos o que está acontecendo. Ou seja, vamos ajustar a lista do menu conforme nossa proposta de projeto:
/*imasters/web/css/main.css*/
/*alterar a linha abaixo*/
#menu{
width: 1003px;
height: 20px;
margin: 0 auto;
position: relative;
}
/*adicionar o estilo do menu no final do documento, conforme abaixo */
#menu ul{
position:absolute;
top:0;
right:10px;
}
#menu ul li{
list-style:none;
display:inline;
}
#menu ul li a{
color: #3FB4C1;
display:block;
padding: 5px 15px;
float:left;
font:14px Arial, Helvetica, sans-serif;
}
#menu ul li a:hover{
color: #ffffff;
background:#3FB4C1;
text-decoration:none;
}
Perfeito, agora já podemos acessar no nosso navegador o endereço “http://imasters.tut.br/” e visualizar algo assim:
Conclusão
Usamos muito a linha de comando para fazer o trabalho mais ‘lento’ e agilizamos ao máximo o nosso projeto. Porém, não é realmente emocionante criar tudo pela linha de comando, especialmente para um projeto Web. Agora temos tudo o que precisamos para criar páginas Web que interagem com o banco de dados. Vimos como exibir o menu – tabela ‘categoria’ . Listamos pela coluna ‘nome’ e usamos o slug para rotear.
Como foi explicado no primeiro artigo, um projeto symfony é feito de aplicações. Cada aplicativo é dividido em módulos. Um módulo é ‘auto-suficiente’ em código PHP que representa uma característica da aplicação (módulo da API, por exemplo), ou um conjunto de manipulações que o usuário pode fazer em um modelo de objeto (o módulo home, por exemplo). Temos no módulo home o componente responsável pelo menu. Ou seja, o método que cria o menu! Através do docrtrine, buscamos os dados do banco de dados, de maneira muito simples. Portanto, dentro do próprio módulo você fará toda a regra de negócio relativo aquele módulo. Para mmelhor entendimento , acesse: www.symfony-project.org
No próximo artigo vamos trabalhar os dados no gerenciador de conteúdo. Vamos entender como criar um gerenciador através de uma outra aplicação, aqui definida por backend. Até lá!