Wednesday, December 19, 2012

Symfony2 - Load different templates based on user agent

If you want to load different templates for different user agents while keeping the same backend code base, you can accomplish this simply in 2 ways.

  1.  Responsive Template
  2. Load different templates against user agents.
In this blog post I'm trying to demonstrate the option 2 (load different templates against user agents)

The trick is to use RequestFormat in symfony

1. Create a Request Listener

php app/console generate:bundle --namespace=Acme/RequestListenerBundle --format=yml


Note: You don't need Controller, Tests directories

Past the below code to AcmeRequestListnerBundle.php

getRequest();

        if(preg_match('/(alcatel|amoi|android|avantgo|blackberry|benq|cell|cricket|docomo|elaine|htc|iemobile|iphone|ipad|ipaq|ipod|j2me|java|midp|mini|mmp|mobi|motorola|nec-|nokia|palm|panasonic|philips|phone|playbook|sagem|sharp|sie-|silk|smartphone|sony|symbian|t-mobile|telus|up\.browser|up\.link|vodafone|wap|webos|wireless|xda|xoom|zte)/i', $request->headers->get('user-agent')))
        {
            $request->setRequestFormat('mobile', 'text/html');
        }else {
            $request->setRequestFormat('html', 'text/html');
        }
    }

    private function setFormat (\Symfony\Component\HttpFoundation\Request $request, $format='html') {
        $request->setRequestFormat($format, 'text/html');
    }
}

2. Create a test action in your controller

Action 

    /**
     * @Route("/test", name="_demo_test")
     * @Template()
     */
    public function testAction()
    {
        return array(
            'name' => 'Thilanga Pitigala',
        );
    }

Note: Run
php app/console router:debug | grep _demo_test
and verify the newly created action and the router

Template
Create the template for newly created action

Acme/DemoBundle/Resources/views/Demo/test.html.twig

{% extends "AcmeDemoBundle::layout.html.twig" %}

{% block title "Hello " %}

{% block content %}
    

Hello Desktop !

{% endblock %}

2. Create a Service using RequestListener

Add below code to config.yml

services:
    acme.listener.request:
        class: Acme\RequestListenerBundle\AcmeRequestListenerBundle
        tags:
            - { name: kernel.event_listener, event: kernel.request, method: onKernelRequest }

Note: run
php app/console container:debug | grep acme.listener.request
  and That will output the newly created service

2. Test RequestListener service

Try visiting the web applications from mobile device. It will throw an error complaining about missing test.mobile.twig file.

Create the test.mobile.twig file in Acme/DemoBundle/Resources/views/Demo/test.html.twig as we created the test.html.twig template.

Now you will be able to see the mobile template from mobile devices while desktop template load for desktop agents.

By that way we can load different templates for different agents without doing any responsive templates.

Happy Coding..

Monday, December 17, 2012

Symfony2 - Setup an Application in a minute

1. Download

Download the Symfony Standard Edition from http://symfony.com/download (at the moment of writing this post latest stable version is 2.1)

cd /home/user/Downloads/
wget --content-disposition 'http://symfony.com/download?v=Symfony_Standard_Vendors_2.1.4.tgz'
tar -zxvf Symfony_Standard_Vendors_2.1.4.tgz
mv Symfony /var/www/symfony

Then Point /var/www/symfony/web directory to the your web server

2. Configuration


Now We are going to use app.php as the main index file instead of playing with app_dev.php within the development enviroment.

vim web/app.php

Replace your app.php with the below code


// Make group permissions stick in cache/log dirs
umask(0002);

use Symfony\Component\ClassLoader\ApcClassLoader;
use Symfony\Component\HttpFoundation\Request;

$loader = require_once __DIR__.'/../app/bootstrap.php.cache';
require_once __DIR__.'/../app/AppKernel.php';

$env = 'prod';

if (isset($_SERVER['HTTP_HOST'])) {
    if (preg_match('/(localhost|local\.)/', $_SERVER['HTTP_HOST'])) {
        $env = 'dev';
    }
}

$kernel = new AppKernel($env, $env == 'dev');
$kernel->loadClassCache();
$request = Request::createFromGlobals();
$response = $kernel->handle($request);
$response->send();
$kernel->terminate($request, $response);

Load your Symfony site by typing http://localhost/symfony in your web browser
Now you can access Symfony Development environment without visiting to app_dev.php.