Question: I have a website with a full browser and jQuery Mobile interface and users can switch between the two. Their preference is stored in a cookie. By default the site serves the full version to visitors whitout a preference cookie, but to make it better for modern smartphone users I want their default to be JQM. So, I have this code in the constructor of my base controller class:

```
class BaseController
{

    protected $mobile;  // must be 0 or 1, cookies can't handle boolean 'false'

    public function __construct()
    {
        if (isset($_COOKIE['mobile']))
        {
            $this->mobile = $_COOKIE['mobile'];
        }
        else
        {
            $this->mobile = $this->isSmartphoneWithCookies();
            setcookie("mobile", $this->mobile, time() + 7776000, '/', ''); // 90 days
        }
    }

    private function isSmartphoneWithCookies()
    {
        $SMARTPHONE_WITH_COOKIES = "android.+mobile|blackberry|ip(hone|od)|opera m(ob|in)i";

        return preg_match("/$SMARTPHONE_WITH_COOKIES/i", $_SERVER['HTTP_USER_AGENT']) ? 1 : 0;
    }

    // the rest of my controller class....
}

```

Here I prefer speed to accuracy, so I am not looking for a slower, up-to-date lookup service as suggested here: [Simple Smart Phone detection](https://stackoverflow.com/questions/5122566/simple-smart-phone-detection)

Just a quick indication that the visitor has one of the current top smartphone/tablet browsers that support cookies and JQM.

Can someone suggest an improvement for my $SMARTPHONE\_WITH\_COOKIES? Or point me to a collection of UA signatures that fit my use case? Specifically, is it safe to have blackberry in the list? Am I overlooking a popular capable browser?

Answer: 
By design, the primary UI selector for my app is the user. I do not want to delegate that to a detection script. The bit of detection in question is just to give a clever default. It is a risky feature, because a false positive (for example a smartphone without cookie support) can make my site totally inaccessible to some users. So if it fails, it needs to fail towards the standard interface.

For what it's worth, I considered the following:

* Opera Mini doesn't have good enough javascript support for my JQM
app.
* Opera Mobile running on Android is a major category that I would
have loved to catch, but I am not confident enough that I can
correctly pick all of that out of the UA string.
* I considered "windows phone os 7", but decided it will date too quickly
* The subset of Blackberry browsers that qualify is also too tricky to detect
simply, so rather than risk a false positive, I decided to drop the
whole tier.

So, what I am left with is:

```
$SMARTPHONE_WITH_COOKIES = "android.+mobile|iphone|ipod";

```

The cost of keeping it this light and simple is that I will have to reconsider this question again every two years or so. I will also have many mobile visitors that will need to do an extra click to get the mobile version.
Personally, I wouldn't want to rely on maintaining a string of user agents. New devices are popuping up like nobody's business, and I've even had a user-agent name change on me and screw up my detection process (Kindle Fire's Silk browser).

An alternative approach is to test for device capabilities. The [WURFL](http://wurfl.sourceforge.net/php_index.php) database is a good starting point. Despite some recent [licensing changes](http://wurfl.sourceforge.net/license.php) that prohibit derivative works, they still have a public repository that you can download and use on your site.

Below are some capabilities that would be useful for testing an A-Grade device:

```
$requestingDevice = $wurflManager->getDeviceForHttpRequest($_SERVER);

$is_wireless = ($requestingDevice->getCapability('is_wireless_device') == 'true');
$is_tablet = ($requestingDevice->getCapability('is_tablet') == 'true');
$is_mobile_device = ($iswireless || $istablet);
$supports_cookies = ($requestingDevice->getCapability('cookie_support') == 'true');
$supports_web = ($requestingDevice->getCapability('device_claims_web_support') == 'true');
$supports_javascript = ($requestingDevice->getCapability('ajax_support_javascript') == 'true');
$supports_ajax = ($requestingDevice->getCapability('ajax_xhr_type') != 'none');
$supports_css3 = ($requestingDevice->getCapability('css_rounded_corners') == 'css3');

```