Tip #7 - Tweak Template Names

Cette astuce est également disponible en français.      

WARNING: Some parts of this tip only work with the latest symfony 1.1 version and only if you have updated your .htaccess file.

By default, symfony guesses the template name and directory based on the executed action.

Let's take a simple content module with a static action in the frontend application as an example:

<?php
 
class contentActions extends sfActions
{
  public function executeStatic()
  {
  }
}
 

When calling the content/static action, symfony will load the staticSuccess.php file as the template and it will look for it in the apps/frontend/modules/content/templates/ directory.

symfony adds a Success suffix by default because the previous code is equivalent to this one:

<?php
 
class contentActions extends sfActions
{
  public function executeStatic()
  {
    return sfView::SUCCESS; // sfView::SUCCESS == 'Success'
  }
}
 

As it doesn't make sense for the content/static action to only manage one static file, we need to pass the page as a request parameter to be able to select our template. So, we add a routing rule:

page:
  url:   /static/:page
  param: { module: content, action: static }
 

Now, let's see how we can update the action to load a different template based on the page request parameter.

Change the suffix

The first thing we can do is to change the default Success suffix by explicitly returning the page:

<?php
 
class contentActions extends sfActions
{
  public function executePage($request)
  {
    return $request->getParameter('page');
  }
}
 

Now, if we request the /static/about page, symfony will load the staticabout.php template.

Here is the templates/ directory content for two different pages:

templates/
  staticabout.php
  staticcontact.php
 

Change the template name

Instead of changing the suffix, we can also change the template name like this:

<?php
 
class contentActions extends sfActions
{
  public function executePage($request)
  {
    $this->setTemplate($request->getParameter('page'));
  }
}
 

Now, when requesting the /static/about page, symfony will load the aboutSuccess.php template.

Here is the templates/ directory content:

templates/
  aboutSuccess.php
  contactSuccess.php
 

As the content module can have some other actions, we might want to put all the static templates under a sub-directory. This can be done by prefixing the template name with the sub-directory:

<?php
 
class contentActions extends sfActions
{
  public function executePage($request)
  {
    $this->setTemplate('static/'.$request->getParameter('page'));
  }
}
 

And symfony will now load the static/aboutSuccess.php template.

Here is the templates/ directory content:

templates/
  static/
    aboutSuccess.php
    contactSuccess.php
 

And if we don't want the Success suffix, we can return an empty string:

<?php
 
class contentActions extends sfActions
{
  public function executePage($request)
  {
    $this->setTemplate('static/'.$request->getParameter('page'));
 
    return '';
  }
}
 

And now symfony will load the static/about.php template.

Here is the templates/ directory content:

templates/
  static/
    about.php
    contact.php
 

More fun with the suffix

Let's add a new requirement: The static pages exist in two formats, HTML and XML, and both formats must be available to the end user.

This means that the user can now request /static/about.html or /static/about.xml. And by default, if the user doesn't provide any extension, the action must return the HTML version.

Let's add the extension request parameter in the routing rule:

page:
  url:   /static/:page.:extension
  param: { module: content, action: static, extension: html }
  requirements:
    extension: (html|xml)
 

As an added bonus, we've added a requirement to check the correctness of the extension.

And here is the rewritten action:

<?php
 
class contentActions extends sfActions
{
  public function executePage($request)
  {
    $this->setTemplate('static/'.$request->getParameter('page'));
 
    return '.'.$request->getParameter('extension');
  }
}
 

So, if we request the /static/about page (or /static/about.hml), symfony will load the static/about.html.php template. And if we request the XML version of the page (/static/about.xml), symfony will load the static/about.xml.php template.

Here is the templates/ directory content:

templates/
  static/
    about.html.php
    contact.html.php
    about.xml.php
    contact.xml.php
 

We can also store our templates in sub-directories according to the format:

<?php
 
class contentActions extends sfActions
{
  public function executePage($request)
  {
    $this->setTemplate('static/'.$request->getParameter('extension').'/'.$request->getParameter('page'));
 
    return '';
  }
}
 

Here is the templates/ directory content:

templates/
  static/
    html/
      about.php
      contact.php
    xml/
      about.php
      contact.php
 

In the real life, we would also have changed the response content type for the XML format.

Here is a summary of all the possibilities we have seen in this tip:

// action
return $request->getParameter('page');
// template name
templates/staticabout.php
 
// action
$this->setTemplate($request->getParameter('page'));
// template name
templates/aboutSuccess.php
 
// action
$this->setTemplate('static/'.$request->getParameter('page'));
// template name
templates/static/aboutSuccess.php
 
// action
$this->setTemplate('static/'.$request->getParameter('page'));
return '';
// template name
templates/static/about.php
 
// action
$this->setTemplate('static/'.$request->getParameter('page'));
return '.'.$request->getParameter('extension');
// template name
templates/static/about.html.php
 
// action
$this->setTemplate('static/'.$request->getParameter('extension').'/'.$request->getParameter('page'));
return '';
// template name
templates/static/html/about.php
 

Discussion

#1 | João Barbosa | 2008-02-18 20:57
Very helpful specially the routing definition. Does executePage receives $request or one should do $this->getRequestParameter('page') for instance? Thanks.
#2 | Fabien | 2008-02-18 21:19
In symfony 1.1, executePage() receive $request by default. If you use symfony 1.0, you must use the $this->getRequestParameter().
#3 | Krešo Kunjas | 2008-02-21 09:08
So what parts of this article are 1.1 specific, except for $request->getParameter()
#4 | NiKo | 2008-03-11 15:23
Same question than Krešo :-)
#5 | Steffen | 2008-03-26 16:37
AFAIK the other 1.1 specific part ist the used "dot" seperator used in the routing. Prior to 1.1 only "slash" seperators were allowed here.
Comments on this tip are closed.
© 2007 Fabien Potencier  |  Powered by  Symfony Framework  |  Valid XHTML 1.0 Transitional