Development

Documentation/pt_BR/book/1.0/04-The-Basics-of-Page-Creation

You must first sign up to be able to contribute.

Capítulo 4 - O básico sobre criação de páginas

Curiosamente, o primeiro tutorial que programadores encontram quando aprendem uma nova linguagem ou um framework é aquela que exibe "Hello, Word!" na tela. É estranho pensar do computador como algo que pode cumprimentar o mundo inteiro, desde que cada tentativa no campo da inteligência artificial resultou em habilidades de conversação pobres. Mas symfony não é mais tolo do que nenhum outro programa, e a prova é, você pode criar uma página que diga “Hello, <Seu Nome Aqui>” com ela.

Este capítulo ensinará você como criar um modulo, que é o elemento estrutural das páginas. Você irá também aprender como criar uma página, que é dividida em ''action'' e ''template'', por causa do padrão MVC. Links e forms são o básico da interação web; você verá como inserí-los em um ''template'' e manipulá-los em uma ''action''.

Criando um esqueleto do módulo

Como explicado no Capítulo 2, symfony agrupa páginas em módulos. Antes de criar uma página, você deve criar um módulo, que é inicialmente uma estrutura vazia de arquivos que o symfony pode reconhecer.

A linha de comando do symfony automatiza a criação dos módulos. Você pode simplesmente chamar o comando init-module com o nome da aplicação e o nome do módulo como argumentos. No capítulo anterior, você criou a aplicação myapp. Para adicionar o módulo mymodule para essa aplicação, digite os seguintes comandos:

> cd ~/myproject
> symfony init-module myapp mymodule

>> dir+      ~/myproject/apps/myapp/modules/mymodule
>> dir+      ~/myproject/apps/myapp/modules/mymodule/actions
>> file+     ~/myproject/apps/myapp/modules/mymodule/actions/actions.class.php
>> dir+      ~/myproject/apps/myapp/modules/mymodule/config
>> dir+      ~/myproject/apps/myapp/modules/mymodule/lib
>> dir+      ~/myproject/apps/myapp/modules/mymodule/templates
>> file+     ~/myproject/apps/myapp/modules/mymodule/templates/indexSuccess.php
>> dir+      ~/myproject/apps/myapp/modules/mymodule/validate
>> file+     ~/myproject/test/functional/myapp/mymoduleActionsTest.php
>> tokens    ~/myproject/test/functional/myapp/mymoduleActionsTest.php
>> tokens    ~/myproject/apps/myapp/modules/mymodule/actions/actions.class.php
>> tokens    ~/myproject/apps/myapp/modules/mymodule/templates/indexSuccess.php

Excluindo os diretórios actions/, config/, lib/, templates/, e validate/, este comando criou apenas três arquivos. Um está na pasta test/ que relaciona unit tests, e você não precisará incomodar-se com ela até o Capítulo 15. O arquivo actions.class.php (mostrado na listagem 4-1) redireciona para o módulo default ''congratulation page''. O arquivo templates/indexSuccess.php está vazio.

Listagem 4-1 - O arquivo action padrão gerado em actions/actions.class.php

[php]
<?php

class mymoduleActions extends sfActions
{
  public function executeIndex()
  {
    $this->forward('default', 'module');
  }
}

NOTA Se você ver o arquivo actions.class.php atual, você encontrará mais do que essas poucas linhas, incluindo vários comentários. Isto acontece porque o symfony recomenda usar comentários para documentar seu projeto e preparar cada arquivo de classe para ser compatível com ferramentas como phpDocumentor (http://www.phpdoc.org/).

Para cada novo módulo, symfony cria uma action index. Ela é composta de um método chamado executeIndex e um template chamado indexSuccess.php. A idéia do prefixo execute e do sufixo do Success serão explicados nos capítulos 6 e 7, respectivamente. Por enquanto, você pode considerar como sendo uma convenção de nomenclatura. Você poderá ver a página correspondente (como na figura 4-1) colocando em seu navegador a seguinte URL:

http://localhost/myapp_dev.php/mymodule/index

A action padrão index não será usada neste capítulo, então você pode remover o método executeIndex() do arquivo actions.class.php, e deletar o arquivo indexSuccess.php da pasta templates/.

NOTA Symfony oferece outras maneiras iniciar um módulo além da linha de comando. Um deles é criar os diretórios e arquivos você mesmo. Em muitos casos, as actions e os templates de um módulo são pretendidos para manipular dados de uma tabela. Como o código necessário para criar, recuperar, atualizar, e deletar registros de uma tabela é frequentemente o mesmo, symfony fornece um mecanismo chamado scaffolding para gerar este código para você. Consulte o capítulo 14 para mais informação sobre esta técnica.

Figure 4-1 - Página default gerada automaticamente

Página default gerada automaticamente

Adicionando uma página

No Symfony, a lógica por trás das páginas esta armazenada nas actions, e a parte visual nos templates. Páginas sem nenhuma instrução lógica precisam de uma action vazia.

Adicionando uma Ação (action)

A página "Hello, word!" será acessada através da action myAction. Para criar ela, simplesmente adicione o método executeMyAction na classe mymoduleActions, como mostrado na listagem 4-2.

Listagem 4-2 - Adicionar uma ação é adicionar um método execute na classe correspondente

[php]
<?php

class mymoduleActions extends sfActions
{
  public function executeMyAction()
  {
  }
}

O método é sempre nomeado como execute"Xxx"(), onde a segunda parte é o nome da ação com a primeira letra em maiúsculo.

Agora, se você requisitar a seguinte URL:

http://localhost/myapp_dev.php/mymodule/myAction

o symfony irá reclamar que o template myActionSuccess.php está faltando. Isto é normal; no symfony, uma página é sempre criada por um action e um template.

CUIDADO URLs (não nomes de domínio) são case-sensitive, e é assim no symfony (mesmo os métodos sendo case-insensitive no PHP). Isto significa que se você adicionar um método executemyaction(), ou executeMyaction(), e então você chamar myAction pelo browser, o symfony retornará um erro 404.

-

SIDEBAR URLs são parte da resposta

O symfony contém um sistema de roteamento que permite ter uma separação completa entre o nome real da action e a forma que a URL é chamada. Isto permite um formato customizado da URL como parte da resposta. Você é limitado não pela estrutura de arquivo nem pelos parâmetros do pedido; a URL para uma action pode ser a frase que você quiser. Por exemplo, a chamada à ação index de um módulo chamado article geralmente é assim:

http://localhost/myapp_dev.php/article/index?id=123

Esta URL recupera artigo na base de dados. Neste exemplo, recupera um artigo (com id=123) da seção Europa que discute especificamente finanças da França. Mas a URL pode ser escrita de uma maneira completamente diferente com uma mudança simples no arquivo de configuração routing.yml:

http://localhost/articles/europe/france/finance.html

Não somente a URL se torna amigável aos mecanismos de busca, como também ela é significativa para o usuário, que pode então usar a barra do endereço como uma pseudo linha de comando para fazer pesquisas, como a seguinte:

http://localhost/articles/tagged/finance+france+euro

Symfony sabe como analisar e gerar URLs inteligentes para o usuário. O sistema do roteamento analisa automaticamente os parâmetros de uma URL inteligente e os torna disponíveis à ação. Formata também os hyperlinks incluídos na resposta de modo que pareçam "espertos." Você aprenderá mais sobre esta característica no Capítulo 9.

Em geral, isto significa que a maneira que você nomeia as ações de suas aplicações não deve ser influenciada pela maneira que você usa para chamar uma URL, mas pelas funções das ações na aplicação. Um nome da ação explica o que a ação faz realmente, e é frequentemente um verbo na forma infinitivo (como mostrar, listar, editar, e assim por diante). Os nomes da ação podem ser feitos totalmente invisíveis ao usuário, assim não hesite em usar nomes explícitos para a ação (como o listByName ou showWithComments). Você economiza em comentários do código para explicar a função da ação, e o código será muito mais fácil de ler.

Adicionando um Template

A ação (action) precisa de um template para renderizar. Um template é um arquivo situado no diretório templates/ de um módulo, nomeado pela ação e pela terminação da ação. A terminação padrão é “success,” assim o arquivo de template para a ação myAction deve se chamar myActionSuccess.php.

Templates são feitos para conter somente o código para apresentação, então tente manter nele o minimo de código PHP que puder. De fato, uma página que indica “Hello, mundo!” pode ser um template tão simples quanto esse da listagem 4-3.

Listagem 4-3 - O Template mymodule/templates/myActionSuccess.php

[php]
<p>Hello, world!</p>

Se você necessitar executar algum código PHP no template, você deve evitar de usar a sintaxe usual do PHP, como mostrado na listagem 4-4. Então, escreva seus templates usando a sintaxe alternativa do PHP, como mostrado na listagem 4-5, para manter o código compreensível para não programadores PHP. Não somente o código final será identado corretamente, mas ajudar-lhe-á também a manter o código PHP complexo na ação, porque somente as estruturas de controle (if, foreach, while, e assim por diante) têm uma sintaxe alternativa.

Listagem 4-4 - A sintaxe usual do PHP, bom para Actions, mas ruim para Templates

[php]
<p>Hello, world!</p>
<?php

if ($test)
{
  echo "<p>".time()."</p>";
}

?>

Listagem 4-5 - A sintaxe PHP alternativa, boa para Templates

[php]
<p>Hello, world!</p>
<?php if ($test): ?>
<p><?php echo time(); ?></p>
<?php endif; ?>

DICA Uma boa forma de verificar se a sintaxe do template esta legível é o arquivo não conter código HTML impresso pelo PHP ou entre chaves. E na maioria das vezes, ao abrir a tag <?php, você deve fechá-lo com ?> na mesma linha.

Passando informações da action para o template


O trabalho da action é fazer todo o cálculo, recuperação de dados, testes, e setar variáveis para que o template seja exibido ou testado. Symfony faz os atributos da classe da action (acessada através de $this->variableName na action) diretamente acessível ao template no namespace global (via $variableName). As listagens 4-6 e 4-7 mostram como passar a informação da action ao template.

Listagem 4-6 - Setando um atributo na action para ser acessível ao template.

[php]
<?php

class mymoduleActions extends sfActions
{
  public function executeMyAction()
  {
    $today = getdate();
    $this->hour = $today['hours'];
  }
}

Listagem 4-7 - O template pode acessar diretamente um atributo da action

[php]
<p>Hello, world!</p>
<?php if ($hour >= 18): ?>
<p>Or should I say good evening? It's already <?php echo $hour ?>.</p>
<?php endif; ?>

NOTA O template já possui o acesso a algumas partes dos dados sem a necessidade de setar qualquer variável na action. Todo template pode chamar métodos dos objetos $sf_context, $sf_request, $sf_params, e de $sf_user. Eles contém os dados relacionados ao contexto atual, request, parâmetros da requisição e sessão. Você aprenderá logo como usá-los eficientemente.

Obtendo informações do usuário com formulários

Os formulários são uma boa maneira de obter informações do usuário. Escrever formulários e elementos do formulário em HTML pode às vezes ser incômodo, especialmente quando você quer ser suportar XHTML. Você poderia incluir elementos do formulário em templates no symfony da maneira usual, como mostrado na listagem 4-8, mas o symfony fornece os helpers que fazem esta tarefa mais fácil.

Listagem 4-8 - Templates podem incluir código HTML usual

[php]
<p>Hello, world!</p>
<?php if ($hour >= 18): ?>
<p>Or should I say good evening? It's already <?php echo $hour ?>.</p>
<?php endif; ?> 
<form method="post" target="/myapp_dev.php/mymodule/anotherAction">
  <label for="name">What is your name?</label>
  <input type="text" name="name" id="name" value="" />
  <input type="submit" value="Ok" />
</form>

Um helper é uma função PHP definida no symfony que pode ser usada dentro dos templates. Eles geram algum código HTML e é mais rápido usá-lo do que escrever o código HTML. Usando helpers do symfony, você pode ter o mesmo resultado que da listagem 4-8 com o código mostrado na listagem 4-9.

Listagem 4-9 - Isto é mais rápido e fácil se usar helpers para tags HTML

[php]
<p>Hello, world!</p>
<?php if ($hour >= 18): ?>
<p>Or should I say good evening? It's already <?php echo $hour ?>.</p>
<?php endif; ?>
<?php echo form_tag('mymodule/anotherAction') ?>
  <?php echo label_for('name', 'What is your name?') ?>
  <?php echo input_tag('name') ?>
  <?php echo submit_tag('Ok') ?>
</form>

SIDEBAR Helpers estão aqui para ajudar você

Se, no exemplo na listagem 4-9, você pensar que o uso do helper não é realmente a forma mais rápida para escrever HTML, considere isto:

[php]
<?php
$card_list = array(
  'VISA' => 'Visa',
  'MAST' => 'MasterCard',
  'AMEX' => 'American Express',
  'DISC' => 'Discover');
echo select_tag('cc_type', options_for_select($card_list, 'AMEX'));
?>

Isto ira gerar o seguinte HTML:

[php]
<select name="cc_type" id="cc_type">
  <option value="VISA">Visa</option>
  <option value="MAST">MasterCard</option>
  <option value="AMEX" selected="selected">American Express</option>
  <option value="DISC">Discover</option>
</select>

O benefício dos helpers nos templates está na velocidade de codificar, na clareza do código, e na concisão. O único preço a pagar é o tempo para aprender, que terminará quando você finalizar este livro, e o tempo de escrever um atalho em seu editor de texto favorito. Você não é obrigado a usar os helpers do symfony nos templates e pode escrever HTML da maneira que voce sempre fez, mas isto seria uma grande perda de tempo e muito menos divertido.


Note que o uso da tag curta (<?=, equivalente a <?php echo) não é recomendado para aplicações web profissionais, pois seu web server em produção pode entender mais de uma linguagem de scripts e conseqüentemente gerar uma confusão. Adicionalmente, as tags curtas não trabalham com a configuração padrão do PHP e necessitam que usuário as configure para ser ativada. Finalmente, quando você tem que tratar do XML, a validação falha porque <? é uma expressão especial do XML.

A manipulação de formulários merece um capítulo inteiro, pois o symfony fornece muitas ferramentas, na maior parte helpers, para torná-lo mais fácil. Você aprenderá mais sobre estes helpers no Capítulo 10.

Chamando outra action

Você já deve saber que há uma total separação entre um nome da action e a URL usada para a chamar. Assim se você criar um link para anotherAction em um template como na listagem 4-10, funcionará somente com o roteamento default. Se você decidir mais tarde mudar a forma das URLs, então você necessitará rever todos os templates para mudar todos os hyperlinks.

Listagem 4-1 - Hyperlinks, a maneira classica

[php]
<a href="/myapp_dev.php/mymodule/anotherAction?name=anonymous">
  I never say my name
</a>

Para evitar essa confusão, você deve sempre usar o helper link_to() para criar hyperlinks às actions da sua aplicação. A listagem 4-11 demonstra o uso do helper para hyperlink.

Listagem 4-11 O Helper link_to()

[php]
<p>Hello, world!</p>
<?php if ($hour >= 18): ?>
<p>Or should I say good evening? It's already <?php echo $hour ?>.</p>
<?php endif; ?>
<?php echo form_tag('mymodule/anotherAction') ?>
  <?php echo label_for('name', 'What is your name?') ?>
  <?php echo input_tag('name') ?>
  <?php echo submit_tag('Ok') ?>
  <?php echo link_to('I never say my name','mymodule/anotherAction?name=anonymous') ?>
</form>

O HTML resultante será o mesmo que o anterior, exceto que quando você muda suas regras de roteamento, todos os templates se comportarão corretamente e reformatarão a URLs conformemente.

O helper link_to(), como muitos outros helpers, aceita outros argumentos para opções especiais e atributos adicionais da tag. A listagem 4-12 mostra um exemplo de um argumento opcional e o HTML resultante. O argumento opcional é qualquer array associativo ou uma simples string que tenha os pares key=value separados por espaços em branco.

Listagem 4-12 - Muitos helpers aceitam um argumento opcional

[php
// Option argument as an associative array
<?php echo link_to('I never say my name', 'mymodule/anotherAction?name=anonymous',
  array(
    'class'    => 'special_link',
    'confirm'  => 'Are you sure?',
    'absolute' => true
)) ?>

// Option argument as a string
<?php echo link_to('I never say my name', 'mymodule/anotherAction?name=anonymous',
  'class=special_link confirm=Are you sure? absolute=true') ?>

// Both calls output the same
 => <a class="special_link" onclick="return confirm('Are you sure?');"
    href="http://localhost/myapp_dev.php/mymodule/anotherAction/name/anonymous">
    I never say my name</a>

Sempre que você usa um helper do symfony que imprime uma tag HTML, você pode inserir atributos adicionais da tag (como o atributo da classe no exemplo da listagem 4-12) no argumento. Você mesmo pode escrever estes atributos da maneira "rápida-e-suja" do HTML 4.0 (sem aspas duplas), e o symfony irá imprimí-los em um XHTML formatado. Esta é uma outra razão porque os helpers são mais rápidos de se escrever HTML.

NOTA
Porque isto requer uma analise gramatical e transformação adicionais, a sintaxe com string é uma pouco mais lenta do que a sintaxe com array.

Como os helpers de formulário, os helpers de link são numerosos e têm muitas opções. O Capítulo 9 descrevê-os em detalhes.

Obtendo informação da requisição

Quando o usuário envia a informação através de um formulário (geralmente em um pedido via POST) ou através da URL (requisição GET), você pode recuperar os dados relacionados da action com o método getRequestParameter() do objeto sfActions. A listagem 4-13 mostra como, no anotherAction, você recupera o valor do parâmetro name.

Listagem 4-13 - Obtendo dados de um parâmetro da requisição na action

[php]
<?php

class mymoduleActions extends sfActions
{
  ...

  public function executeAnotherAction()
  {
    $this->name = $this->getRequestParameter('name');
  }
}

Se a manipulação dos dados for simples, você não necessita usar a action para recuperar os parâmetros do pedido. O template tem acesso a um objeto chamado $sf_params, que oferece um método get() para recuperar os parâmetros do pedido, assim como o getRequestParameter() na action.

Se executeAnotherAction() estiver vazio, a listagem 4-14 mostra como o template anotherActionSuccess.php recuperaria o mesmo parâmetro.

Listagem 4-14 - Obtendo dados do parâmetro do pedido diretamente no Template

[php]
<p>Hello, <?php echo $sf_params->get('name') ?>!</p>

NOTA Por que não usar as variáveis $_POST, $_GET, ou $_REQUEST? Porque seu URL está formatado diferentemente (como em http://localhost/articles/europe/france/finance.html, sem o ? nem =), as variáveis usuais de PHP não funcionam, e somente o sistema de roteamento consegue recuperar os parâmetros do pedido. E você pode querer ter filtros de input para impedir code injection, que é somente possível se você mantiver todos os parâmetros do pedido em um local limpo.


O objeto $sf_params é mais poderoso do que apenas um array equivalente. Por exemplo, se você quiser somente testar a existência de um parâmetro do pedido, você pode simplesmente usar o método de $sf_params->has() em vez de testar o valor real com get(), como na listagem 4-15.

Listagem 4-15 - Testando a existência do parâmetro do pedido no template

[php]
<?php if ($sf_params->has('name')): ?>
  <p>Hello, <?php echo $sf_params->get('name') ?>!</p>
<?php else: ?>
  <p>Hello, John Doe!</p>
<?php endif; ?>

Você pode já ter percebido que isto pode ser escrito em uma única linha. Como com a maioria dos métodos getter no symfony, o método getRequestParameter() na action e o método $sf_params->get() no template (que, de fato, chama o mesmo método no mesmo objeto) aceitam um segundo argumento: o valor default a ser usado se o parâmetro do pedido não estiver presente.

[php]
<p>Hello, <?php echo $sf_params->get('name', 'John Doe') ?>!</p>

Sumário

No symfony, as páginas são compostas de uma action (um método no arquivo actions/actions.class.php definido como executável) e de um template (um arquivo no diretório templates/, terminando geralmente com Success.php). São agrupados em módulos, de acordo com sua função na aplicação. Escrever templates é facilitado pelos helpers, que são funções fornecidas pelo symfony e retornam código HTML. Você precisa pensar na URL como parte da resposta, que pode ser formatada como necessario, e por isso você deve deixar de usar referências diretas à URL no nome da action ou do parâmetro de retorno da requisição.

Uma vez que você saiba estes princípios básicos, você já pode escrever uma aplicação web inteira com symfony. Mas isso pode ser um tanto demorado e para resolver isso, cada tarefa que você fará durante o desenvolvimento da aplicação é facilitado por alguma característica do symfony. É por isso que o livro não termina agora.