views:

96

answers:

1

Hi,

I'm using Symfony 1.2.7. My web is in several languages, each of one is in a subdomain like en.example.com, es.example.com. If the user enters into example.com, I want to redirect him to his language. I also want to have support staging.example.com and redirect to es.staging.example.com and en.staging.example.com so I can test everything before the deployment.

I have the following code that works both on index.php and frontend_dev.php. My question is, can you improve it? is there a better or cleaner way? Thanks!

require_once(dirname(__FILE__).'/../config/ProjectConfiguration.class.php');

$configuration = ProjectConfiguration::getApplicationConfiguration('frontend', 'dev', true);
$context = sfContext::createInstance($configuration);

// get the domain parts as an array
$host = array_reverse(explode('.', $_SERVER['HTTP_HOST']));
list($tld, $domain, $subdomain) = $host;

// determine which subdomain we're looking at
$app = ($subdomain == 'staging') ? $subdomain2=$host[3] : $subdomain;

if(empty($app) || $app == 'www')
{
  $browser_languages = $context->getRequest()->getLanguages();

  foreach($browser_languages as $language)
  {
    $allowed_culture = in_array($language, sfConfig::get('app_languagesAvailable'));
    if($allowed_culture)
    {
      $domain = $subdomain ? $subdomain.'.'.$domain : $domain;
      $url = 'http://'.str_replace($domain.'.'.$tld, $language.'.'.$domain.'.'.$tld, $_SERVER['HTTP_HOST']).$_SERVER['REQUEST_URI'];

      $context->getController()->redirect($url);
      break;
    }
  }
}

$context->dispatch();

Update Solution: Custom filter

<?php

class subdomainFilter extends sfFilter
{
    public function execute($filterChain)
    {
        $context = $this->getContext();
        $user = $this->getContext()->getUser();
        $request = $this->getContext()->getRequest();

        // get the domain parts as an array
        $host = array_reverse(explode('.', $request->getHost()));
        list($tld, $domain) = $host;
        $subdomain2 = $host[3];
        $subdomain = $host[2];

        // determine which subdomain we're looking at
        $app = ($host[2] == 'staging') ? $subdomain2 : $subdomain;

        if(empty($app) || $app == 'www')
        {
          // if first time
          if ($this->isFirstCall())
          {
            $browser_languages = $request->getLanguages();
            // set default lang, for API as CURL doesn't set the language
            $lang = sfConfig::get('app_default_culture');

            foreach($browser_languages as $language)
            {
              $allowed_culture = in_array($language, sfConfig::get('app_languagesAvailable'));
              if($allowed_culture)
              {
                $lang = $language;
                break;
              }
            }
          }else {
            // Get user culture
            $lang = $user->getCulture();
          }

          $domain = $subdomain ? $subdomain.'.'.$domain : $domain;
          $url = str_replace($domain.'.'.$tld, $lang.'.'.$domain.'.'.$tld, $request->getURI());
          $context->getController()->redirect($url);
        }

        $filterChain->execute();
    }
}
+1  A: 

Using Symfony's routing system is the proper solution for these kind of issues.

Take a look at http://www.symfony-project.org/jobeet/1_2/Doctrine/en/05 for general routing info and at http://www.symfony-project.org/blog/2009/03/02/call-the-expert-adding-subdomain-requirements-to-routing-yml for advanced routing issues.

Note: I strongly suggest updating to sf 1.4 because 1.2 isn't maintained anymore. (http://www.symfony-project.org/tutorial/1_4/en/upgrade)

Treur
thanks treur. I've already checked those articles and they don't solve my problem. All the actions are the same on es.example.com and en.example.com. And I want to redirect the main domain depending on the language. I'm going to upgrade in a few weeks, when we have time to check everything works right.
fesja
Hmm. I see. In that case I think using a filter is a more elegant solution.Furthermore, filters can be enabled/disabled with cookies which will removes the unnecessary overhead when a user is already on the right subdomain: http://www.symfony-project.org/book/1_2/06-Inside-the-Controller-Layer#chapter_06_sub_building_your_own_filter
Treur
that's better. However, what if the current user goes to example.com. I have his cookie, and I know he wants the web in English; but if I don't check the host, he will be using www.example.com in English instead of en.example.com. It seams that I always have to check the host for the subdomain. If he is a user (getCulture()), if not, check browser languages.
fesja
Cookies are domain based (not sure if they are subdomain based by default, but it's customizable), so the cookies for example.com won't be available for en.example.com and vice-versa
Treur
we are using the cookie domain .example.com so we have the same cookie for all (except for staging.example.com, that's only for testing). We want that. I've updated the code as a filter. thanks!
fesja