How to create an optimized version of your website for the iPhone in symfony 1.1

symfony 1.1 introduces native support for different formats and mime-types. This means that the same model and controller can have different templates based on the requested format. The default format is still HTML but symfony supports several other formats out of the box as defined in the factories.yml file:

request:
  class: sfWebRequest
    param:
      formats:
        txt:  text/plain
        js:   [application/javascript, application/x-javascript, text/javascript]
        css:  text/css
        json: [application/json, application/x-json]
        xml:  [text/xml, application/xml, application/x-xml]
        rdf:  application/rdf+xml
        atom: application/atom+xml
 

Each format is associated with one or more mime-types. These mime-types are used to automatically determine the requested format by parsing the Accept HTTP header. This comes in very handy if you want to make your data available via a browser and expose them as a Web Service. To change the format of the response, a Web Service client can just change the Accept header as shown below:

$ curl -H "Accept: application/xml"  http://ws.example.com/api/article # to get a XML representation of the data
$ curl -H "Accept: application/json" http://ws.example.com/api/article # to get a JSON representation of the data

Supporting different formats is as easy as creating different templates. So, let's say the web service is managed by an api/article action. Here is the list of templates you have to create in apps/frontend/modules/api/templates to support HTML, XML, and JSON formats:

  • articleSuccess.php
  • articleSuccess.xml.php
  • articleSuccess.json.php

By default, symfony will change the response Content-Type according to the format, and for all non-HTML formats, the layout will be disabled. Even partials and layouts can be different based on the requested format. For example, if you include a list partial in a template, the loaded partial name will depend on the current format:

  • _list.php
  • _list.xml.php
  • _list.json.php

Let's take another example. You want to create some stylesheets or JavaScript files on the fly. As you can't always rely on the browser Accept HTTP header for those cases, you can force a format by using the special sf_format variable in your routing rules. Here is how to create a route for a dynamic stylesheet:

css1:
  url:   /css/dynamic1.css
  param: { module: css, action: dynamic, sf_format: css }
 

You can also use the sf_format variable in the URL pattern to allow several formats for one action:

api_article:
  url:   /api/article.:sf_format
  param: { module: api, action: article }
  requirements:
    sf_format: (?:html|xml|json)
 

Most of the time, you don't have to change a single line in your actions to support new formats; but if you really need to do something special for a format, you can call the $request->getRequestFormat() to get the current format and act accordingly.

Ok, now for the fun part! Let's say you want to create an optimized version of your website for the iPhone. The iphone format does not exist by default but it's pretty easy to configure one. First, we need a way to determine that a request comes from an iPhone. If the User-Agent header contains the words Mobile and Safari, we can safely guess that the browser is an iPhone. We can put this logic in the ProjectConfiguration class by registering a listener for the request.filter_parameters event:

// config/ProjectConfiguration.class.php
class ProjectConfiguration extends sfProjectConfiguration
{
  public function setup()
  {
    // ...
 
    $this->dispatcher->connect('request.filter_parameters', array($this, 'filterRequestParameters'));
  }
 
  public function filterRequestParameters(sfEvent $event, $parameters)
  {
    $request = $event->getSubject();
 
    if (preg_match('#Mobile/.+Safari#i', $request->getHttpHeader('User-Agent')))
    {
      $request->setRequestFormat('iphone');
    }
 
    return $parameters;
  }
}
 

Now, everytime a request comes in, the filterParameters() method is called and if the browser is an iPhone, the request format is changed to iphone.

That's all! Now, every request from an iPhone will use *Success.iphone.php templates instead of *Success.php templates.

If you use some special stylesheets of JavaScript files to support the iPhone (for example if you use the iui library), you can also configure the view by listening to the view.configure_format:

class ProjectConfiguration extends sfProjectConfiguration
{
  public function setup()
  {
    // ...
 
    $this->dispatcher->connect('view.configure_format', array($this, 'configureIPhoneFormat'));
  }
 
  public function configureIPhoneFormat(sfEvent $event)
  {
    if ('iphone' == $event['format'])
    {
      // add some CSS, stylesheet, or whatever you want
    }
  }
}
 

Today, Apple launched the new iPhone 2. To celebrate this event, I'm pleased to announce that the symfony API documentation is now available for the iPhone with a specific interface as you can see in the screenshot below.

Thanks to the new format support in symfony 1.1, developing websites that supports Web Services, API or the iPhone has never been easier. Supporting a new format is as easy as creating a new set of templates. Enjoy!

Comments

You guys are doing such an amazing job making us NOT THINK about anything!.
thanks.
sf still the best

Symfony FTW!
Thank you for this beautiful framework!
Is not just a framework, is a way of life!
Thank you!
It took me a few minutes to get this up and running. There are a few minor corrections to your example.

The method name, 'filterRequestParameters' doesn't match the one in your connect call, 'filterParameters'.

I needed to replace '$dispatcher' with '$this->dispatcher' - maybe that was implied by '// ...'?

And you also need to create a layout called 'layout.iphone.php'.

:)

Other than that -- it's gorgeous!


// config/ProjectConfiguration.class.php
class ProjectConfiguration extends sfProjectConfiguration
{
public function setup()
{
// ...

$this->dispatcher->connect('request.filter_parameters', array($this, 'filterRequestParameters'));
}

public function filterRequestParameters(sfEvent $event, $parameters)
{
$request = $event->getSubject();

if (preg_match('#Mobile/.+Safari#i', $request->getHttpHeader('User-Agent')))
{
$request->setRequestFormat('iphone');
}

return $parameters;
}
}


@dave: thanks for the feedback. I've fixed the examples.
Ah, hells yeah. This is nice. I am currently spitting out json and html for one of my projects, but this method is much cleaner.

Looking forward to start using 1.1.

Do validators work with this?
This looks impressing!

Is there some docs on customizing sfProjectConfiguration and an explained list of those events like view.configure_format you can modify?
@Jordi: All the events are described in the symfony book:

http://www.symfony-project.org/book/1_1/17-Extending-Symfony#Built-In%20Events
Holy shot. That's the release I've waited for a long time :) Great job and thank you for your efforts, and making symfony OSS!

I'm looking forward to the 1.1 stable release.
Great! Me as well looking forward to start projects based on 1.1.
I presume the iPhone stuff is identically working for the iPod-Touch as well, as the latter is based on the same software system as the iPhone (e.g. Mobile Safari)?
Cheers RAPHAEL
What a very great news :p
Nice, but why iPhone? There are tons of other mobile phones too... Rather than optimizing for iPhone, it'd be much better to optimize for all small screen devices.
iPhone will rule da world.
the routing rule :
url: /api/article:.sf_format
should be:
url: /api/article.:sf_format ?
@reeze: you're right. It was a typo. Thanks.
0089. Personal Unsecured Loans Online With Very Bad Credit
04316. Alternative Student Loans Bad Credit
04874. Very Bad Credit Personal Loans
04950. Bad Credit High Loan Personal Risk Unsecured
05363. Free Mp3 Ringtones
06489. Free Samsung T100 Ringtones
07057. Annual Credit Report Free
07633. Ringtones For Verizon Cell Phones
08753. Ringophone Verizon Polyphonic Ringtones
0882. Download Free Polyphonic Ringtones
00857. Personal Loan Michigan
04340. Guaranteed Bad Credit Student Loans
04885. Free Bad Credit Personal Loans
04995. Find Unsecured Personal Loans For Very Very Bad Credit
05315. Lg Ringtones
06429. Free Ringback Ringtones
07044. National Free Credit Report
07655. Free Downloadable Ringtones For Verizon
08780. Free Ringtones For Verizon Customers
08874. Free Download Ringtones
00870. Personal Loan Guaranteed Bad Credit Loans Online Application
04345. Alternative Student Loans For Students With Bad Credit
04816. Personal Loans Bad Credit
0495. Instant Approval Unsecured Personal Loans For Bad Credit
05380. Free Cell Phone Ringtones
06445. Free Christian Ringtones
07045. Free Instant Credit Reports
0768. Ringtones Free Verizon
08731. Making Ringtones For Verizon Phones
08894. Free Mobile Ringtones Download
00891. No Credit Personal Loans
04366. Bad Credit Loan Student
04822. Bad Credit Personal Loan For Auto Purchase
04931. Unsecured Personal Loans Bad Credit Uk
05392. Totally Free Ringtones
06456. Free Nokia 1260 Ringtones
07052. Free Annual Credit Reports
07649. Verizon V3M Ringtones
08716. Ringtones For Verizon Phones
08860. Download Free Poly Ringtones
00895. Personal Loan Washington
0431. Alternative Student Loans Bad Credit
04861. Personal Loans For Bad Credit Repair
0496. Bad Poor Horrible Credit Unsecured Personal Loans
05379. Free Samsung Ringtones
06459. Free Cellphone Ringtones
07022. My Free Credit Report
07652. Verizon Kyocera Cell Phone Ringtones
08715. Thehonorsystem Free Verizon Ringtones
08895. Download Free Cingular Ringtones
00882. Fast Cash Personal Loans
04398. School Guaranteed Bank Student Loans Bad Credit
0486. Bad Credit Long Term Personal Loans
04956. Guaranteed Unsecured Personal Loan
05353. Free Composer Ringtones
06466. Free Samsung Keypress Ringtones
07040. Free Government Credit Report
07632. Free Ringtones For Verizon Cellular Phones
08764. Polyphonic Ringtones Verizon Wireless
08839. Free Download Nokia Ringtones
00841. Bad Credit Unsecured Personal Loan
04331. Maine Student Loans For Students With Bad Credit
0483. Instant Online Guaranteed Approval Personal Loans Bad Credit
04965. Guaranteed Unsecured Personal Loans
05343. Free Nokia Ringtones
0649. Free Actual Song Ringtones
07016. Free Yearly Credit Report
07631. Free Ringtones For Motorola Verizon
08722. Coolfreeringtones Verizon Polyphonic Ringtones
08842. Free Ringtones Download To Pc
HID Kits
Car DVD
HID Kits
00899. Low Interest Personal Loans
04372. Credit Card Loan Bad Credit Mortgage Auto Student Business
04875. Apply Bad Credit Easy Loans Personal
04955. Unsecured Fixed Rate Personal Loans
05328. Motorola V60 Free Ringtones
06420. Free No Catch Ringtones
0708. Consumer Free Credit Report
07614. Free Verizon Polyphonic Ringtones
08769. Ringtones For Verizon Cell Phones
0884. Motorola Download Free Ringtones
00884. Guaranteed Personal Loans
04322. Free Student Loans With Bad Credit
04894. Same Day Personal Loans For People With Bad Credit
04988. Unsecured Personal Loans Bad Credit No Home
05348. Free Polyphonic Ringtones USA
06440. Free At&T Ringtones
07013. Linkall Order Free Consumer Credit Report Bureau Check Score
07667. Ringtones For Verizon Wireless
08743. Verizon Music Ringtones
08892. Samsung Ringtones Free Download Ring Tones For Cell Phone

09374. Download Free Ringtones
0949. Free Gospel Ringtones
09559. Free Cell Phones Ringtones
09665. Totally Free Ringtones
00878. Bad Credit Personal Loans
0430. Student Loans For Students With Bad Credit
0484. Unsecured Personal Loan Bad Credit
0495. Personal Credit Hard Money Unsecured Loans
05324. Free Virgin Mobile Ringtones
06425. 100% Free Ringtones
07020. Totally Free Credit Report
07680. Verizon Ringback Ringtones
08771. Free Ringtones For Verizon Wireless Samsung Sch A650 Phones
08846. Wap Sites To Download Free Samsung Ringtones
00833. Guaranteed Personal Loan Approval
04344. Private Student Loans For Bad Credit
04814. Bad Credit Loan Personal Unsecured
04961. Buy Cheap Unsecured Personal Loans Bad Credit
05392. Totally Free Ringtones
06497. Free Download Nokia Ringtones
07053. Experian Check Free Credit Report
07687. Can You Get Ringtones For A Verizon Camera Phone
08796. Free Ringtones For Verizon Wireless Customers For Lg Phones
08851. Download Free Real Music Ringtones
00810. Unsecured Bad Credit Personal Loans
04376. Private Bad Credit Student Loans
04811. Personal Bad Credit Loan
04942. Bad Credit Unsecured Personal Loans Online Instantly
05383. Free Ringtone Converter
06427. Free Nokia 5125 Ringtones
07093. Free Instant Credit Report
07667. Verizon Get It Now Ringtones
08757. Ringtones For Verizon Wireless Phones
08834. Download Free Mp3 Ringtones
09228. Totally Free Ringtones
00880. Very Bad Credit Personal Loans
04317. Guaranteed Student Loan People Bad Credit
04810. Secured Personal Loans For People With Bad Credit
04993. Personal Unsecured Bad Credit Loans
05387. Free Mp3 Ringtones
0648. Free Ringtones For Virgin Mobile
07070. Free Credit Report No Credit Card Required
07671. Polyphonic Ringtones For Verizon Wireless
08739. Free Verizon Ringtones
08825. Free Download Free Ringtones
09236. Keypress Ringtones
00839. Secured Personal Loan
04338. Bad Debt Loan Student Credit
04822. Bad Credit Loan Personal Unsecured
04930. Bad Credit Unsecured Loan Personal Loan
05372. Mosquito Ringtone
06444. Free Mp3 Ringtones
07044. Free Online Credit Report No Credit Card Needed
07685. Coolfreeringtones Verizon Ringtones
08782. Gospel Ringtones Free Motorola V265 Verizon
08890. Samsung Ringtones Free Download Ring Tones For Cell Phone
09229. Free Verizon Ringtones
00819. Guaranteed Online Personal Loans
04332. Bad College Credit Loan Personal Student
04844. Bad Credit Long Term Personal Loans
04932. Bill Consolidation + Unsecured Personal Loan
05352. Real Sound Ringtones
06455. Free Samsung T100 Ringtones
07075. Government Legislation Free Annual Credit Report
07645. Samsung Verizon Ringtones
08722. Verizon Kyocera Cell Phone Ringtones
08870. Download Free Ringtones Voicemail Messages
09253. Free Ringtones Verizon
00823. Second Chance Secured Personal Loan
04342. Free Student Loans With Bad Credit
04856. Small Bad Credit Personal Loans
04968. Bad Credit Loans Unsecured Personal
05370. Ringtones For A Samsung
06417. Free Hip Hop Ringtones
07067. Free Online Credit Reports With No Credit Card Required
07657. Free Ringtones Verizon Wireless Phones
08775. Free Verizon Wireless Ringtones
08853. Thumbplay Free Download Nokia Ringtones
09232. Free Tracfone Ringtones
From looking at this post I assume templates can be created for things like SOAP and REST calls as well? In other words, instead of a template that works on an iPhone, a template could be created to present the sfActions as web services? I may be off the mark a bit (please forgive me, I'm a PM, not a coder...)
UA-sniffing and device specific versions of a website. What year is this? 1997? Haven't you guys heard of Web Standards?

One may make a site for small screens. But to make a site for a specific device is really bad practice.

And the iPhone support @media CSS-rules. That should be the first choice if you want to arrange stuff for the small screen. Incidentally that also is supported by Opera and will be by Firefox 3.1 and therefore also Fennec.

Using the wrong tool for a job is not a good route to go down, even if that tool is really well designed.
Lars, what if you want a different html output for the iphone ?
@Hans

a. If your pages are so bloated that you must use different HTML output I would presume you need serious IA refactoring.

b. The very point of Apples marketing is that the iPhone should not get mobile specific versions of a website. And they specifically chose not to honor @media handheld but uses @media screen rules. By using such a device a customer has chosen to view the full version. Ergo: use "@media screen and max-width()" if you need to adapt.

Incidentally, that will also work for all users of Opera Mini (which is a larger audience than the iPhone's!) and Opera Mobile, as well as the upcoming Fennec.

c. UA sniffing has been proven beyond all reasonable doubt to be a faulty solution. It will only lead to UA-spoofing. We really have been there before! To repeat a previous mistake but expect a different outcome is just plain stupid.

So:

If you really must send alternate content to mobile devices (not just the iPhone), the least sucky solution is to use a different URL and let the user choose.

Of course that can lead to surprises when the mobile version ranks higher on Google. Just like many sites using the faulty approach of having "print versions" experience today.

But as I said to begin with. If your IA is bad, that is where you should attack the problem. It is better than creating new ones.

Comments are closed.

To ensure that comments stay relevant, they are closed for old posts.