On a recent project I needed a way to know if a user is using a mobile device to visit the site I was building and, if so, I wanted a little more info about the device, OS and browser used.
Before baking my own solution, I checked existing solutions such as the great WURFL, well known framework’s own solutions like CodeIgniter’s and other quite good scripts like php-mobile-detect, detectmobilebrowsers.mobi or mobiforge.com.
None did what I needed in a simple and lightweight way:
WURFL
- Not straightforward to implement.
- Device database updates have to be done manually and periodically (at least twice a year) to stay up to date (Ughh).
- Heavy on the server (poor performance).
CodeIgniter’s user agent class
Works well for mobile detection but it does not tell you either the OS or browser used.
php-mobile-detect
I like this one a lot but, unfortunately it doesn’t detect every browser/os/device I wanted, it has some bugs and I haven’t tested its regular expressions.
detectmobilebrowsers.mobi
Very good script but, unfortunately it doesn’t detect every browser/os/device I wanted. However, I used it as a reference.
mobiforge.com
This script is more suited towards detecting old mobile devices (feature phones).
So in the end I made my own script.
All I wanted was a helper function that would execute once per page load and set some global variables.
Those of you who prefer or need an OOP approach should modify the php-mobile-detect class to your needs.
Here’s my function:
<?php
/*
* Lightweight detector of mobile devices, OSs & browsers
* Copyright 2012 Túbal Martín (email: tubalmartin@gmail.com)
* License: GPL2
*/
if ( ! function_exists('mobile_detector') )
{
// Global vars
$is_mobile = false;
$is_iphone = $is_ipad = $is_kindle = false;
$is_ios = $is_android = $is_webos = $is_palmos = $is_windows = $is_symbian = $is_bbos = $is_bada = false;
$is_opera_mobile = $is_webkit_mobile = $is_firefox_mobile = $is_ie_mobile = $is_netfront = $is_uc_browser = false;
function mobile_detector($debug = false)
{
global $is_mobile;
// Check user agent string
$agent = isset($_SERVER['HTTP_USER_AGENT']) ? $_SERVER['HTTP_USER_AGENT'] : '';
if (empty($agent)) {
return;
}
$mobile_devices = array(
'is_iphone' => 'iphone',
'is_ipad' => 'ipad',
'is_kindle' => 'kindle'
);
$mobile_oss = array(
'is_ios' => 'ip(hone|ad|od)',
'is_android' => 'android',
'is_webos' => '(web|hpw)os',
'is_palmos' => 'palm(\s?os|source)',
'is_windows' => 'windows (phone|ce)',
'is_symbian' => 'symbian(\s?os|)|symbos',
'is_bbos' => 'blackberry(.*?version\/\d+|\d+\/\d+)',
'is_bada' => 'bada'
);
$mobile_browsers = array(
'is_opera_mobile' => 'opera (mobi|mini)', // Opera Mobile or Mini
'is_webkit_mobile' => '(android|nokia|webos|hpwos|blackberry).*?webkit|webkit.*?(mobile|kindle|bolt|skyfire|dolfin|iris)', // Webkit mobile
'is_firefox_mobile' => 'fennec', // Firefox mobile
'is_ie_mobile' => 'iemobile|windows ce', // IE mobile
'is_netfront' => 'netfront|kindle|psp|blazer|jasmine', // Netfront
'is_uc_browser' => 'ucweb' // UC browser
);
$groups = array($mobile_devices, $mobile_oss, $mobile_browsers);
foreach ($groups as $group) {
foreach ($group as $name => $regex) {
if (preg_match('/'.$regex.'/i', $agent)) {
global $$name;
$is_mobile = $$name = true;
break;
}
}
}
// Fallbacks
if ($is_mobile === false) {
$regex = 'nokia|motorola|sony|ericsson|lge?(-|;|\/|\s)|htc|samsung|asus|mobile|phone|tablet|pocket|wap|wireless|up\.browser|up\.link|j2me|midp|cldc|kddi|mmp|obigo|novarra|teleca|openwave|uzardweb|pre\/|hiptop|avantgo|plucker|xiino|elaine|vodafone|sprint|o2';
$accept = isset($_SERVER['HTTP_ACCEPT']) ? $_SERVER['HTTP_ACCEPT'] : '';
if (false !== strpos($accept,'text/vnd.wap.wml')
|| false !== strpos($accept,'application/vnd.wap.xhtml+xml')
|| isset($_SERVER['HTTP_X_WAP_PROFILE'])
|| isset($_SERVER['HTTP_PROFILE'])
|| preg_match('/'.$regex.'/i', $agent)
) {
$is_mobile = true;
}
}
// DEBUGGER OUTPUT
if ($debug === true) {
echo '<strong>User Agent: '.$agent.'</strong><br>';
foreach ($GLOBALS as $k => $v) {
if (strpos($k, 'is_') !== false) {
echo '<span style="color:'.($v ? 'green':'red').';">$'.$k.'</span><br>';
}
}
}
}
// execute inmmediatly
mobile_detector();
}
I have created a Gist so you can download or fork the code.
This function should only be called once per page load and preferably as soon as possible.
This function adds the following variables to the global scope:
Is it a mobile?
- $is_mobile
Any famous device?
- $is_iphone (Apple iPhone)
- $is_ipad (Apple iPad)
- $is_kindle (Amazon Kindle)
What mobile OS?
- $is_android (Android OS)
- $is_bada (Bada OS)
- $is_bbos (Blackberry OS)
- $is_ios (Apple iOS)
- $is_palmos (Palm OS)
- $is_symbian (Symbian OS)
- $is_webos (Hp WebOS)
- $is_windows (Windows Phone OS and older)
What mobile browser?
- $is_firefox_mobile (Mozilla Fennec)
- $is_ie_mobile (IE)
- $is_netfront (NetFront)
- $is_opera_mobile (Opera Mobile or Mini)
- $is_uc_browser (UC Browser)
- $is_webkit_mobile (Webkit)
The initial value of these variables is false.
You can test/debug the plugin results (debug mode) here.
If you need to debug the function, call it passing true as a parameter and the function will output the results.
If you use Wordpress to build websites and you’re reading this post let me tell you I already developed a plugin for Wordpress based on this function.
Share your thoughts!!