{{{ #!WikiMarkdown Capítulo 2 - Explorando o Código ================================ A primeira vista, o código por de traz de uma aplicação gerenciada pelo Symfony pode parecer assustador. Ele consiste de muitos diretórios e scripts, os arquivos são uma mistura de classes PHP, HTML, ou mesmo uma mistura dos dois. Você também verá referencias para classes que não serão encontradas em lugar algum dentro da pasta da aplicação, e que a profundidade dos diretórios pode se estender até 6 níveis. Mas uma vez que você compreender a razão por detrás de toda esta complexidade, tudo parecerá tão natural para você que você não trocaria o Symfony por qualquer outras estruturas de aplicação. Este capitulo tenta diminuir esta sensação intimidante. O Padrão MVC ------------ O Symfony é baseado no clássico padrão de design web conhecido como Arquitetura MVC (MVC Architecture), que consiste de três niveis: * a modelagem (model) representa as informações com que a aplicação opera -- sua lógica de negócio. * a visualização (view) renderiza a modelagem em uma página de internet pronta para interação com o usuário. * o controlador (controller) responde às ações do usuário e invoca mudanças na modelagem ou visualização conforme necessário. A figura 2-1 ilustra o padrão MVC. A arquitetura MVC separa a lógica do negócio (model) e a apresentação (view) resultando em grande manutencibilidade. Por exemplo, se sua aplicação deve rodar em tanto padrões voltados à web browsers e dispositivos móveis, você apenas precisa de uma nova visualização; você pode manter o controlador e modelagem original. O controlador ajuda a esconder os detalhes do protocolo utilizado para a requisição (HTTP, console, mail, entre outros) da modelagem e da visualização. E a modelagem abstrai a lógica dos dados, o que faz com que a visualização e a ação independente de, por exemplo, do tipo de banco de dados utilizado pela aplicação. Figura 2-1 - O padrão MVC ![O padrão MVC](http://www.symfony-project.com/images/book/trunk/F0201.png "O padrão MVC") ### As camadas do MVC Para ajudar você a compreender as vantagens do MVC, vamos ver como se converte uma aplicação básica em PHP para uma aplicação que se utilize da arquitetura MVC. Uma lista mensagens para um aplicação de weblog será um exemplo perfeito. #### Programação Simples Em um simples arquivo PHP, exibir uma lista de entradas de uma base de dados pode parecer com o script apresentado na listagem 2-1. Listagem 2-1 - Um script simples [php] List of Posts

List of Posts

\n"; printf("\t\t\n", $row['date']); printf("\t\t\n", $row['title']); echo "\t\n"; } ?>
DateTitle
%s %s
Isto é rápido para escrever, rápido para executar e impossível para manter. Os maiores problemas com este código são os seguintes: * Não há verificação de erros (o que acontece se a base de dados falha?) * HTML e PHP estão misturados, inclusive entralaçados entre si. * O código está amarrado à uma base de dados mySQL. #### Isolando a apresentação As funções `echo` e `printf` na listagem 2-1 tornam o código difícil de ser lido. Modificar código HTML de modo a melhorar o layout é um problema com a atual sintaxe. Portanto o código pode ser dividido em duas partes. Primeiro, o código PHP puro, com todas as lógicas de negócio, e um script controlador, como exibido na lista 2-2. Listagem 2-2 - A parte Controladora, em `index.php` [php] O código HTML, contendo uma modelagem com sintaxes PHP, é armazenado no script de visualização, como exibido na listagem 2-3; Listagem 2-3 - A parte de visualização, em `view.php` [php] List of Posts

List of Posts

DateTitle
Uma boa maneira de determinar se uma visualização esta limpa o suficiente é se esta contem apenas o mínimo de código PHP, de modo que possa ser compreendida por um designer HTML com o mínimo de conhecimento em PHP. Os comandos mais comuns em visualizações são `echo, if/endif, foreach/endforeach` e só! Além disso, não deve haver nenhum código PHP invocando tags HTML. Toda a lógica é movida para o script controlador, que contem apenas puro código PHP, sem nenhum HTML. De fato, você deveria imaginar que um mesmo controlador poderia ser reutilizado para uma apresentação completamente diferente, como num arquivo PDF ou numa estrutura XML. #### Isolando a Manipulação de Dados Muitos dos scripts de controle são dedicados à manipulação de dados. Mas e se você precisar da lista de mensagens para um outro controlador, um que alimentasse um RSS feed com as mensagens do weblog por exemplo? E se você quiser manter todas os comandos de acesso da base de dados em um lugar, e evitar duplicação de código? E se você decidir mudar a modelagem dos dados de modo a mudar o nome da tabela `post` para `weblog_post`? E se você quiser mudar para uma base de dados PostgreSQL ao invés do MySQL? Para tornar isto possível, você precisa remover todos os códigos que manipulam dados do controlador e pô-los em outro script, chamado de modelo, como ilustrado na listagem 2-4. Listagem 2-4 - A parte de modelagem, em `model.php` [php] A listagem 2-5 ilustra o controlador revisado. Listagem 2-5 - A parte de controle, revisada, em `index.php` [php] O controlador torna se fácil de ler. Sua única tarefa é pegar os dados da modelagem e passá-los para o visualizador. Em aplicações mais complexas, o controlador também trata as requisições, as seções de usuário, as autenticações, entre outros. O uso de nomes explícitos para as funções da modelagem tornam os comentários desnecessários no controlador. A modelagem é dedicada ao acesso aos dados, e pode ser organizado de acordo. Todos os parâmetros que não precisam da camada de dados (como parâmetros de requisição) devem ser enviados ao controlador e não acessados diretamente pela modelagem. As funções de modelagem podem ser facilmente reutilizadas em outros controladores. ### Separando camadas além do MVC O princípio da arquitetura MVC é separar o código em três camadas, de acordo com suas naturezas. Códigos voltados aos dados são armazenados na modelagem, a interface na visualização, e a lógica da aplicação no controlador. Outros padrões adicionais de design pode tornar a experiência de desenvolver códigos ainda mais simples. As camadas de modelagem, da visualização, e do controlador podem ser subdivididas em mais outras camadas. #### Abstraindo a Base de Dados A camada de modelagem pode ser dividida em uma camada de acesso aos dados e uma camada de abstração da base de dados. Deste modo, funções de acesso aos dados não utilizarão comandos dependentes do tipo de base de dados utilizada, mas outras funções que executarão os comandos em seu lugar. se você trocar a base de dados mais tarde, apenas a camada de abstração precisará ser atualizada. Um exemplo de uma camada de acesso é exibida na listagem 2-6, seguido de um exemplo de uma camada de abstração na listagem 2-7. Listagem 2-6 - A camada de abstração da modelagem [php] Como você pode ver, nenhuma função dependente de uma base de dados específica é encontrada na camada de acesso, tornando-a independente de base de dados. Além disto, as funções criadas na camada de abstração podem ser reutilizadas em muitos outras funções que acessam à base de dados. >**NOTE** >Os exemplos na listagem 2-6 e 2-7 podem não ser muitos satisfatórios, e há muito trabalho para se obter uma abstração completa de uma base de dados (abstrair o código SQL através de um construtor independente de base de dados, movendo todas as funções para uma classe, entre outros). Mas o objetivo deste livro não é mostrar como escrever todo o código, e você irá perceber no Capítulo 8 que o symfony faz nativamente muito bem toda a abstração. #### Elementos de Vizualização A camada de visualização pode também se beneficiar com alguma separação de códigos. Págins web de uma mesma aplicação geralmente contem elementos comuns entre si: os cabeçalhos, o layout gráfico, o rodapé, e o modo de navegar. Apenas o conteúdo da página muda. Por isto que a visualização é separada em uma camada de layout e uma camada de modelo. O layout geralmente é global para a aplicação, ou a um grupo de páginas. O modelo apenas da forma ao modo como as variáveis são disponibilizadas pelo controlador. Um pouco de lógica é necessária para fazer com que estes componentes trabalhem em conjunto, e a camada lógica da visualização irá servir para esta função. De acordo com estes principios, a camada de visualização exibida na Listagem 2-3 pode ser separada em três partes, como exibido nas Listagems 2-8, 2-9 e 2-10. Listagem 2-8 - A camada de modelo da visualização, em mytemplate.php [php]

List of Posts

DateTitle
Listagem 2-9 - A camada lógica da visualização [php] Listagem 2-10 - A camada de layout da visualização [php] <?php echo $title ?> #### Ações e o Controlador Principal O controlador não faz muito no exemplo anterior, mas em aplicações reais o controlador tem muito trabalho por fazer. Uma importante parte deste trabalho geralmente é comum à todos os controladores de uma aplicação. As comuns tarefas de tratar requisições, garantir a segurança da aplicação, carregar as configurações da aplicação, entre outras atividades semelhantes. É por isto que que o controlador geralmente é dividido em uma camada principal, que é única para toda a aplicação, e uma camada de ações, que contem apenas os códigos específicos de controle de uma única página. Uma das grandes vantagens do controlador principal é a de que ele oferece um modo único de acessar a aplicação inteira. Se você decidir fechar o acesso à aplicação, você precisa apenas editar o script do controlador principal. Em uma aplicação sem um controlador principal, cada controlador individual teria de ser desligado. #### Orientação à Objeto Todos os exemplos citados anteriormente utilizando uma programação procedural. A capacidade de programar orientado a objetos nas linguagens atuais fazem a tarefa de programar ainda mais fácil, uma vez que objetos pode encapsular código, herdar de outros, e permitir uma simples convenção de nomes. Implementando uma arquitetura MVC em uma linguagem não-orientada à objetos gera problemas com a nomenclatura de variáveis e duplicação de código, e o código resultante tende a ser difícil de ler. Orientação à objetos permite desenvolvedores à lidar com tais coisas como objetos de visualização, objetos de controle, e classes de modelagem, e transformar todas as funções dos exemplos anteriores em métodos. É um dos pontos altos das arquiteturas MVC. >**TIP** >Se você deseja aprender mais sobre padrões de design para aplicações web utilizando orientação à objetos, leia ''Patterns of Enterprise Application Architecture'', de Martin Fowler (Addison-Wesley, ISBN: 0-32112-742-0). Exemplos de códigos nos livros de Fowler são em java ou C#, mas ambas as linguagens são de fácil compreensão para um desenvolvedor PHP ### Implementação MVC no Symfony Só um pouco! Para apenas uma página listando mensagens de um weblog, quantos componentes são necessários ? Como ilustrado na figura 2-2, nós temos as seguintes partes: * Camada de Modelagen * Abstração * Acesso * Camada de Visualização * Lógica * Modelo * Layout * Camada de Controle * Controle Principal * Ações Sete scripts -- um monte de arquivos para abrir e modificar cada vez que você criar uma nova página! Entretanto, Symfony torna as coisas mais fáceis. Tirando o melhor da arquitetura MVC, Symfony as implementa de modo a tornar o desenvolvimento de aplicações uma atividade rápida e simples. Primeiro, o controlador principal e o layout são comuns à todas as atividades da aplicação. Você pode ter diversos controladores e layouts, mas precisa apenas de um. O controlador principal é um componente com apenas lógica MVC pura, e você nunca irá precisar escrever um pois Symfony irá gerá-lo para você. A outra boa notícia é que as classes da camada de modelagem também são geradas automaticamente, baseados na sua estrutura de dados. Este é um trabalho para a biblioteca Propel, que fornece esqueletos de classes e geração de código. Se o Propel encontrar atributos Foreign Key ou campos de dados, ele irá criar acessos especiais e métodos diferenciados que tornarão a manipulação dos dados algo simples como café da manhã. E a abstração da base de dados é algo completamente invisível para você, porque é tratada por outro componente, chamado Creole. Portanto se você decidir trocar o tipo de base de dados a ser usada na sua aplicação, você não terá de re-escrever nenhuma linha de código. Você apenas precisará trocar um parâmetro de configuração. E a última coisa é que a camada de visualização pode ser facilmente traduzida com um simples arquivo de configuração, necessitando nenhuma programação adicional. Figura 2-2 - Diagrama de fluxo do Symfony ![Diagrama de fluxo do Symfony ](http://www.symfony-project.com/images/book/trunk/F0202.png "Diagrama de fluxo do Symfony") Isso significa que a lista de mensagens descrita em nosso exemplo irá precisar apenas três arquivos para trabalhar com o Symfony, como exibido nas listas 2-11, 2-12 e 2-13. Listagem 2-11 - ''Ações'', na camada de controle, em `myproject/apps/myapp/modules/weblog/actions/actions.class.php` [php] posts = PostPeer::doSelect(new Criteria()); } } ?> Listagem 2-12 - ''Modelo'', na camada de visualização, em `myproject/apps/myapp/modules/weblog/templates/listSuccess.php` [php]

List of Posts

DateTitle
getDate() ?> getTitle() ?>
Listagem 2-13 - ''Lógica'', em `myproject/apps/myapp/modules/weblog/config/view.yml` listSuccess: metas: { title: List of Posts } Você ainda terá de definir um layout, mas uma vez definido este poderá ser reutilizado por todas as demais janelas da aplicação. Listagem 2-14 - ''Layout'', em `myproject/apps/myapp/modules/weblog/layout/layout.php` [php] getRaw('sf_content') ?> E é apenas isso que você precisa. Este é o código necessário para exibir a mesma página do simples script exibido na Listagem 2-1. O resto (fazer todos os componentes trabalharem juntos) é gerenciado pelo Symfony. Se você contar as linhas, você verá que criar a lista utilizando a arquitetura MVC com o Symfony não requer muito mais tempo ou código que escrevendo um arquivo simples. Entretanto, ele lhe fornece grandes vantagens: organização clara do código, reusabilidade, flexibilidade, e muito mais. Como um bônus, você possui conformidade XHTML, capacidades de debug, facilidade de configuração, abstração da base de dados, redirecionamento inteligente de URLs, múltiplos ambientes, e muitas ferramentas de desenvolvimento a mais. ### Classes Principais do Symfony A implementação do MVC no symfony utiliza diversas classes que você irá encontrar com alguma freqüência neste livro: * `sfController` é a classe de controle. Ela decodifica as requisições e as entrega às Ações * `sfRequest` armazena todas os elementos de requisição (parâmetros, cookies, cabeçalhos, entre outros) * `sfResponde` contém os cabeçalhos de resposta e conteúdo. Este é o objeto que irá eventualmente ser convertido nos códigos HTML que serão enviados ao usuários. * O contexto singleton (recebido de `sfContext::getInstance()`) armazena a referência para todos os objetos principais e configurações correntes, sendo acessível de qualquer lugar. Você aprenderá mais sobre estes objetos no Capítulo 6. Como você pode ver, todas as classes do Symfony utilizam o prefixo `sf`, assim como as variáveis principais nos modelos do Symfony. Isto deve ajudar a evitar colisão de nomes com suas classes e variáveis, e tornar as classes do framework faceis de serem reconhecidas. >**NOTE** >Entre os padrões de códigos utilizados pelo Symfony, o padrão utilizado para nomenclatura de variáveis e classes é o `UpperCamelCase`. Duas exceções existem: as classes do Symfony iniciam com sf, o que é minúsculo, e as variáveis encontrados nos modelos utilizam a sintaxe separada com underscore (_). Organização de Código --------------------- Agora que você conhece os diferentes componentes de uma aplicação Symfony, você provavelmente deve estar se perguntando como estes são organizados. Symfony organiza o código em uma estrutura de projeto e põe os arquivos deste em uma estrutura em árvore padrão. ### Estrutura de Pojeto: Aplicações (Applications), Módulos (Modules) e Ações (Actions) No symfony, um projeto é um conjunto de serviços e operações disponíveis em um dado domínio, compartilhando o mesmo modelo de objetos. Dentro de um projeto, as operações são agrupadas logicamente em aplicações. As aplicações podem ser executadas independentemente das outras aplicações de um mesmo projeto. Em muitos casos, um projeto irá conter duas aplicações: uma para aplicações `front-office` e outras para aplicações `back-office`, compartilhando uma mesma base de dados. Mas você também pode ter projetos contendo diversos pequenos sites, cada um como uma aplicação diferente. Perceba que os hyperlinks entre aplicações devem estar todos em forma absoluta. cada aplicação é um conjunto de um ou mais módulos. Um módulo geralmente representa uma página ou um grupo de páginas com um propósito similar. Por exemplo você pode ter os módulos `Home`, `artigos`, `ajuda`, `carrinhoDeCompras`, `conta`, entre outros. Módulos guardam ações, que representam as várias ações que podem ser feitas em um módulo. Por exemplo, um módulo `carrinhoDeCompras` pode possuir ações do tipo `adicionar`, `exibir` e `atualizar`. Geralmente, ações podem ser descritas com um verbo. Trabalhar com ações é quase o mesmo que trabalhar com páginas de uma aplicação web clássica, apesar de que duas mesmas ações acabem resultando na mesma página (adicionar um comentário num weblog irá exibir a janela de comentários com o novo comentário) >**TIP** >Se isto representa muitos níveis para um projeto inicial, é muito fácil agrupar todas as ações em um único módulo, de modo a manter a estrutura de arquivos simples. A medida que a aplicação se torna mais complexa, será necessário separar as ações em módulos separados. Como mencionado no Capítulo 1, reescrever código de modo a melhorar sua estrutura ou facilitar sua leitura (mas preservando seu comportamento) é chamado `refactoring`, e você irá fazer isso um monte quando aplicando os princípios RAD. A figura 2-3 ilustra uma amostra da organização de um projeto para um weblog, com uma estrutura projeto/aplicaçao/módulo/ação. Mas esteja ciente de que a real estrutura em arvore do projeto será diferente da ilustrada na figura. Figura 2-3 - Exemplo de organização de código ![Exemplo de organização de código](http://www.symfony-project.com/images/book/trunk/F0203.png "Exemplo de organização de código") ### Estrutura de Arquivos Todos os projetos geralmente compartilham o mesmo tipo de conteúdo, como os seguintes: * uma base de dados, como MySQL ou PostgreSQL * arquivos estáticos (HTML, imagens, códigos javascript, planilhas, entre outros) * arquivos enviados pelos uusários e administradores do site * classes e bilbliotecas PHP * bibliotecas adicionais (scripts desenvolvidos por terceiros) * arquivos de batch (scripts que serão executados por uma linha de comando) * arquivos de log (registrados pelo aplicativo e/ou servidor) * arquivos de configuração Symfony oferece uma estrutura padrão de arquivos em árvore para organizar todo este conteúdo de uma maneira lógica, consistente com as escolhas de arquitetura (padrões MVC e agrupamentos projeto/aplicação/módulo). Esta é a estrutura em árvores que será automaticamente criada quando inicializado um projeto, aplicação ou módulo. É claro, você pode personalizar isto completamente, para reorganizar os arquivos e diretórios de acordo com sua conveniência ou para atender às necessidades dos clientes. #### Raiz da Estrutura de Árvore Estes são os diretórios encontrados na raiz de um projeto symfony. A tabela 2-1 descreve o conteúdo destes diretórios. apps/ frontend/ backend/ batch/ cache/ config/ data/ sql/ doc/ lib/ model/ log/ plugins/ test/ unit/ functional/ web/ css/ images/ js/ uploads/ Tabela 2-1 - Diretório Raiz Diretório | Descrição ----------|---------- `apps/` | Contém um diretório para cada aplicação do projeto (geralmente, `frontend` e `backend` para o Front Office e Back Office. `batch/` | Contém os scripts PHP chamados por uma linha de comando ou despertador, de modo a executar processos em `batch`. `cache/` | Contém as versões armazenadas de configuração, e (se você o ativar) a versão do armazenador de ações e modelos do projeto. O mecanismo armazenador (detalhado no Capítulo 12 usa estes arquivos para acelerar o tempo de respostas às requisições da web. Cada aplicação possuirá um subdiretório aqui, contendo arquivos PHP e HTML pré-processados. `config/` | Armazena as configurações geral do projeto. `data/` | Aqui você pode armazenar arquivos de dados do projeto, como um esquema de uma base de dados, comandos SQL que criam tabelas, ou mesmo o arquivo de uma base de dados SQLite. `doc/` | Armazena a documentação do projeto, incluindo os seus documentos e os gerados pelo PHPdoc. `lib/` | Dedicado às bibliotecas e classes adicionais, geradas por terceiros. Aqui você pode adicionar códigos que devem ser compartilhados entre suas aplicações. `model/` Subdiretório que armazena o modelo de objetos do projeto. (ver Capítulo 8). `log/` | Armazena os arquivos de log gerados diretamente pelo symfony. Pode conter arquivos de log dos servidores web, ou logs das bases de dados de qualquer parte do projeto. Symfony cria um arquivo de log para cada aplicação e ambiente (arquivos de log são discutidos no Capítulo 16. `plugins/`| Armazena os plug-ins instalados na aplicação (plug-ins são discutidos no Capítulo 17). `test/` | Contém testes de unidade e de função escritor em PHP e compatível com o framework de testes do Symfony (discutidos no Capítulo 15). Durante a configuração do projeto, symfony automaticamente adiciona alguns modelos com alguns testes básicos. `web/` | A raiz para o servidor web. Os únicos arquivos acessíveis pela Internet se encontram neste diretório. #### Estrutura em Árvore da Aplicação A estrutura em árvore dos diretórios de todas as aplicações é sempre a mesma. A tabela 2-2 descreve o conteúdo dos subdiretórios: apps/ [nome da aplicação]/ config/ i18n/ lib/ modules/ templates/ layout.php error.php error.txt Tabela 2-2 - Subdiretórios das Aplicações Diretório | Descrição ------------|---------- `config/` | Armazena um grande conjunto de arquivos de configuração YAML. Aqui é onde se encontram a maior parte das configurações da aplicação, separado dos parâmetros padrões que podem ser encontrados no próprio framework. Repare que os parâmetros padrões podem ser sobrescritos aqui se necessário. Você irá aprender mais sobre como configurar uma aplicação no Capitulo 5. `i18n/` | contêm os arquivos de internacionalização da aplicação -- geralmente arquivos de tradução da interface (Capítulo 13 lida com a internacionalização). Você pode ignorar este diretório se utilizar a base de dados para internacionalizar a aplicação. `lib/` | Contém classes e bibliotecas específicas para esta aplicação. `modules/` | armazena todos os módulos que contém as funcionalidades da aplicação. `templates/`| lista os modelos globais da aplicação -- os compartilhados por todos os módulos. Por default, ele contém o arquivo layout.php, que é o layout principal onde o módulo de modelos é insiderido. >**NOTE** >Os diretórios `i18n/`, `i18n` e `modules/` se encontram vazios para cada nova aplicação. As classes de uma aplicação não são capazes de acessar métodos e atributos de outras aplicações de um mesmo projeto. Perceba também que os hyperlinks entre duas aplicações de um mesmo projetos devem se encontrar no modo absoluto. Você tem de manter isto em mente durante as etapas iniciais, onde você decide em quantas aplicações o projeto será dividido. #### Estrutura em Árvores dos Módulos Cada aplicação possui um ou mais módulos. Cada módulo possui seu próprio subdiretório na pasta `modules/`. Abaixo segue uma estrutura em árvore típica de um módulo. A tabela 2-3 descreve o conteúdo de cada diretório. apps/ [aplication name]/ modules/ [module name]/ actions/ actions.class.php config/ lib/ templates/ indexSuccess.php validate/ Tabela 2-3 - Subdiretórios dos Módulos Diretório | Descrição -------------|---------- `actions/` | geralmente contém um único arquivo de classe chamado `actions.class.php`, no qual você pode armazenar todas as ações do modulo. Você também pode escrever diferentes ações para um módulo em arquivos separados. `config/` | Pode conter arquivos de configuração personalizados com os parâmetros locais de cada módulo. `lib/` | Armazena classes e bibliotecas específicas do módulo. `templates/` | Contém o modelo correspondente às ações do módulo. Um modelo padrão, chamado `indexSucess.php`, é criado durante a criação do módulo. `validate/` | Dedicado à arquivos de configuração utilizados para validação de formulários (discutido no Capítulo 10). >**NOTE** >Os diretórios `config/`, `lib/` e `validate/` se encontram vazios para cada novo módulo. #### Estrutura em Árvore da Web Existem poucas particularidades quanto ao diretório web, que é o diretório com as arquivos acessíveis publicamente. Seguindo umas poucas convenções de nomenclatura, é possível criar comportamentos padrões e atalhos úteis para os modelos. Abaixo segue um exemplo da estrutura de um diretório web. Por convenção, os arquivos estáticos são distribuídos nos diretórios listados na tabela 2-4. web/ css/ images/ js/ uploads/ Tabela 2-4 - Subdiretórios Web Diretório | Descrição -------------|---------- `css/` | Contém as planilhas de estilo com extensão `.css` `images/` | Contém as imagens com extensão `.jpg`, `.png` ou `.gif`. `js/` | Armazena os arquivos JavaScript com extensão `.js` `uploads/` | Armazena os arquivos enviados pelos usuários. Apesar do diretório geralmente conter imagens, ele se distingue do diretório de imagens de modo que a sincronização dos servidores de desenvolvimento e produção não afetem as imagens enviadas. >**NOTE** >Mesmo sendo extremamente recomendado que você mantenha a estrutura em árvore padrão, é possível modificar esta de modo a antender suas necessidades, como permitir que um projeto rode em um servidor com diferentes regras para estruturas e convenções de código. Leia o Capítulo 19 para maiores informações sobre modificar a estrutura de arquivos. ## Instrumentos Comuns Algumas técnicas são utilizadas repetidamente no symfony, e você as encontrará com certa freqüência neste livro e em seus próprios projetos. Isto inclui os parâmetros, constantes, e carregadores automáticos de classes. ### Parâmetros Muitas das classes do symfony contém um parâmetro. É um modo conveniente de encapsular atributos com métodos de busca e atribuição. Por exemplo, a classe `sfResponse` armazena os parâmetros que você pode recuperar chamando o método `getParameterHolder()`. Cara parâmetro armazena informação do mesmo modo, como ilustrado na Listagem 2-15. Listagem 2-15 - Usando `sfResponse` [php] $response->getParameterHolder()->set('foo', 'bar'); echo $response->getParameterHolder()->get('foo'); => 'bar' Muitas das classes utilizando um parâmetro disponibilizam métodos alternativos para encurtar o código necessário para operações `get/set`. Para isto se usa o objeto `sfResponse`, de modo que você consegue fazer o mesmo apresentando em Listagem 2-15 com o código da Listagem 2-16. Listagem 2-16 - Utilizando métodos alternativos do `SfResponse` de acesso à parametros [php] $response->setParameter('foo', 'bar'); echo $response->getParameter('foo'); => 'bar' A função `get` do parâmetro aceita valores default como segundo argumento. Isso oferece um útil mecanismo à prova de erros muito mais simples que o obtido com verificações condicionais. Veja a Listagem 2-17 para um exemplo. Listagem 2-17 - Utilizando o valor default do `get` de um parâmetro. [php] // The 'foobar' parameter is not defined, so the getter returns an empty value echo $response->getParameter('foobar'); => null // A default value can be used by putting the getter in a condition if ($response->hasParameter('foobar')) { echo $response->getParameter('foobar'); } else { echo 'default'; } => default // But it is much faster to use the second getter argument for that echo $response->getParameter('foobar', 'default'); => default Parâmetros suportam inclusive `namespaces`. Se você especificar um terceiro argumento para uma função `set` ou `get`, este é utilizado como namespace, e o parêmetro será definido apenas dentro deste. Veja a Listagem 2-18 para um exemplo. Listagem 2-18 - Utilizando namespaces de um parâmetro `sfResponse` [php] $response->setParameter('foo', 'bar1'); $response->setParameter('foo', 'bar2', 'my/name/space'); echo $response->getParameter('foo'); => 'bar1' echo $response->getParameter('foo', null, 'my/name/space'); => 'bar2' É claro, você pode adicionar um parâmetro às suas classes de modo a tirar vantagem de suas facilidades de sintaxe. A Listagem 2-19 mostra como definir uma classe com um parâmetro. Listagem 2-19 - Adicionando um parâmetro à uma classe [php] class MyClass { protected $parameter_holder = null; public function initialize ($parameters = array()) { $this->parameter_holder = new sfParameterHolder(); $this->parameter_holder->add($parameters); } public function getParameterHolder() { return $this->parameter_holder; } } ### Constantes Surpreendentemente, você irá encontrar poucas constantes no Symfony. Isto porque constantes possuem um grave problema no PHP: uma vez definidas, você não pode modifica-las. Portanto o Symfony utiliza seu próprio objeto de configuração, chamado `sfConfig`, que substitui constantes. Ele oferece métodos estáticos para acessar parâmetros de qualquer lugar. A Listagem 2-20 demonstra a utilização de métodos da classe sfConfig. Listagem 2-20 - Utilizando métodos da classe `sfConfig` ao invés de constantes. [php] // Instead of PHP constants, define('SF_FOO', 'bar'); echo SF_FOO; // Symfony uses the sfConfig object sfConfig::set('sf_foo', 'bar'); echo sfConfig::get('sf_foo'); Os métodos de `sfConfig` suportam valores default, e você pode invocar o método `sfCondig::set()` diversas vezes para um mesmo parâmetro para alterar seu valor. O Capítulo 5 explica os métodos de `sfConfig` com mais detalhes. ### Auto carregamento de classes Classicamente, quando você usa um método da classe ou cria um objeto em PHP, você necessita incluir primeiramente a definição da classe [php] include 'classes/MyClass.php'; $myObject = new MyClass(); Mas em projetos grandes, com muitas classes e uma estrutura profunda de diretório, manter-se a par de todo arquivo de classe para incluir, demanda muito tempo. Fornecendo uma função `__autoload()` (ou uma função `spl_autoload_register()`), symfony torna os `includes` desnecessários, e você pode escrever diretamente: [php] $myObject = new MyClass(); Symfony procura então uma definição de `MyClass` em todos os arquivos que terminam com php em um dos diretórios do `lib/` do projeto. Se a definição da classe for encontrada, estará incluída automaticamente. Assim se você armazenar todas suas classes no diretório `lib/`, você não necessita incluir nenhuma classes. Isso porque os projetos symfony geralmente não contêm indicações `include` ou `require`. Para o melhor desempenho, o `autoloading` do symfony faz varre uma lista dos diretórios (definidos em um arquivo de configuração) durante o primeiro pedido. Regista então todas as classes que estes diretórios contêm e armazena a correspondência da classe/larquivo em um arquivo PHP como uma array associativa. Dessa maneira, os pedidos futuros não necessita fazer nenhuma a varredura no diretório. É por isso que você necessita limpar o cache todas as vezes que você adiciona ou move um arquivo de classe em seu projeto chamando o comando `symfony clear-cache command`. Você aprenderá mais sobre o cache no capítulo 12, e sobre a configuração `autoloading` no capítulo 19. Sumário ------- Usar uma estrutura MVC força-o a dividir e organizar seu código de acordo com as convenções de estrutura. O código da apresentação para `view`, o código da manipulação de dados para `model`, e a lógica da manipulação do pedido vai para `controller`. Isto faz a aplicação do padrão MVC muito útil e completamente restringindo. Symfony é uma estrutura MVC escrita em PHP 5. Sua estrutura é projetada para ter o melhor do padrão MVC, mas com uma grande facilidade de utilização. Graças a sua versatilidade e configurabilidade, symfony é apropriado para todos os projetos web. Agora que você compreende a teoria atrás do symfony, você está quase pronto para desenvolver sua primeira aplicação. Mas antes disso, você necessita uma instalação do symfony rodando e funcionando em seu servidor de desenvolvimento. }}}