Chad 2010-05-31

In Symfony 1.4, we can use the view.yml to configure html meta tags:

Code - YMLPlain Text
 
  1. // config/view.yml  
  2.   
  3. default:    
  4.   metas:    
  5.     title:        My Website    
  6.     description:  This is Chad's website     
  7.     keywords:     Chad, website, php, symfony    
  8.     #language:     en    
  9.     #robots:       index, follow    

 

And we can also override the meta values in Symfony actions:

Code - PHPPlain Text
 
  1. // apps/someApp/modules/someModule/actions/actions.class.php  
  2.   
  3. public function executeIndex(sfWebRequest $request){      
  4.         $this->getResponse()->addMeta('title''custom title');  
  5.         // $this->getResponse()->setTitle('custom title') would do the same job as above  
  6.     }  

 

Then if we use the include_metas() and include_title() method at the same time, both of the code above would generate two meta tags for the "title":

Code - HTMLPlain Text
 
  1. // html output  
  2.   
  3. <html>  
  4. <head>  
  5.     <meta name="title" content="My Website" />  
  6.     <title>My Website</title>  
  7.   
  8. ...  

 

Is this possible to have only the title tag and remove the other (the meta name="title" tag is not recognize by browsers anyway)? The answer is yes, and there are a lot of solutions. I think the best way is to subclass the sfWebResponse class and override the getMetas() method:

Code - YMLPlain Text
 
  1. // config/factories.yml  
  2.   
  3. all:  
  4.   response:  
  5.     class: myWebResponse  
Code - PHPPlain Text
 
  1. // lib/myWebResponse.class.php  
  2.   
  3. class myWebResponse extends sfWebResponse  
  4. {     
  5.     public function getMetas()  
  6.     {  
  7.         $metas = parent::getMetas();  
  8.         if(array_key_exists('title',$metas)){  
  9.             unset($metas['title']);  
  10.         }  
  11.         return $metas;  
  12.     }  
  13. }  

 

The code above would remove the the meta name="title" tag and keep the title tag. That's because the include_metas() and include_title() method use different way to generate the tags:

Code - PHPPlain Text
 
  1. // lib/vendor/symfony/lib/helper/AssetHelper.php  
  2.   
  3. function include_metas()  
  4. {  
  5.   $context = sfContext::getInstance();  
  6.   $i18n = sfConfig::get('sf_i18n') ? $context->getI18N() : null;  
  7.   foreach ($context->getResponse()->getMetas() as $name => $content)  
  8.   {  
  9.     echo tag('meta'array('name' => $name'content' => null === $i18n ? $content : $i18n->__($content)))."\n";  
  10.   }  
  11. }  
  12.   
  13. function include_title()  
  14. {  
  15.   $title = sfContext::getInstance()->getResponse()->getTitle();  
  16.   
  17.   echo content_tag('title'$title)."\n";  
  18. }  

 

Obviousely the include_metas() is using sfWebResponse::getMetas(), and include_title() using sfWebResponse::getTitle() to get the values set in the configuration file. Let's have a closer look at these two methods:

Code - PHPPlain Text
 
  1. // lib/vendor/symfony/lib/response/sfWebResponse.class.php  
  2.   
  3. public function getMetas()  
  4. {  
  5.   return $this->metas;  
  6. }  
  7.   
  8. public function getTitle()  
  9. {  
  10.   return isset($this->metas['title']) ? $this->metas['title'] : '';  
  11. }  

 

It's quite clear that these two methods are actually retrieving values from the same array, so it's quite safe to override the sfWebRespose::getMetas() method to let include_metas() exclude the unwanted meta name="title" tag.