PHP-браузер и os-обнаружение, показывающие хром вместо оперы

У меня есть простой скрипт php для определения имени браузера и os. Все идет хорошо, за исключением OPERA, которая отображается как Chrome. Вот мой код:

<?php $user_agent = $_SERVER['HTTP_USER_AGENT']; function getOS() { global $user_agent; $os_platform = 'Unknown OS Platform'; $os_array = array ( '/windows nt 6.2/i' => 'Windows 8', '/windows nt 6.1/i' => 'Windows 7', '/windows nt 6.0/i' => 'Windows Vista', '/windows nt 5.2/i' => 'Windows Server 2003/XP x64', '/windows nt 5.1/i' => 'Windows XP', '/windows xp/i' => 'Windows XP', '/windows nt 5.0/i' => 'Windows 2000', '/windows me/i' => 'Windows ME', '/win98/i' => 'Windows 98', '/win95/i' => 'Windows 95', '/win16/i' => 'Windows 3.11', '/macintosh|mac os x/i' => 'Mac OS X', '/mac_powerpc/i' => 'Mac OS 9', '/linux/i' => 'Linux', '/ubuntu/i' => 'Ubuntu', '/iphone/i' => 'iPhone', '/ipod/i' => 'iPod', '/ipad/i' => 'iPad', '/android/i' => 'Android', '/blackberry/i' => 'BlackBerry', '/webos/i' => 'Mobile' ); foreach ($os_array as $regex => $value) { if (preg_match($regex, $user_agent)) $os_platform = $value; } return $os_platform; } function getBrowser() { global $user_agent; $browser = "Unknown Browser"; $browser_array = array ( '/msie/i' => 'Internet Explorer', '/firefox/i' => 'Firefox', '/safari/i' => 'Safari', '/chrome/i' => 'Chrome', '/opera/i' => 'Opera', '/netscape/i' => 'Netscape', '/maxthon/i' => 'Maxthon', '/konqueror/i' => 'Konqueror', '/mobile/i' => 'Handheld Browser' ); foreach ($browser_array as $regex => $value) { if (preg_match($regex, $user_agent)) $browser = $value; } return $browser; } $user_os = getOS(); $user_browser = getBrowser(); $device_details = '<strong>Browser: </strong>' . $user_browser . '<br /><strong>Operating System: </strong>' . $user_os; print_r($device_details); echo('<br /><br /><br />' . $_SERVER['HTTP_USER_AGENT']); ?> 

Я изменил $ browser_array, добавив / OPR / i в качестве другого регулярного выражения для оперы и разместив регулярное выражение Chrome после 2 регулярных выражений Opera:

  $browser_array = array ( '/msie/i' => 'Internet Explorer', '/firefox/i' => 'Firefox', '/safari/i' => 'Safari', '/OPR/i' => 'Opera', '/opera/i' => 'Opera', '/chrome/i' => 'Chrome', '/netscape/i' => 'Netscape', '/maxthon/i' => 'Maxthon', '/konqueror/i' => 'Konqueror', '/mobile/i' => 'Handheld Browser' ); 

здесь Chrome UA:

 Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/28.0.1500.72 Safari/537.36 

И здесь Opera UA:

 Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/28.0.1500.71 Safari/537.36 OPR/15.0.1147.141 

Логика кода: он находит Opera сначала в цикле, но затем встречает «Chrome», что также соответствует. Таким образом, последний найденный результат сохраняется. Я предлагаю :

 foreach ($browser_array as $regex => $value) { if (preg_match($regex, $user_agent) && $browser == "Unknown Browser") $browser = $value; } 

Таким образом, если браузер уже найден, он не изменит его на новое значение. Не забудьте правильно отсортировать массив.

В вашем случае этот код будет сначала искать Opera (соответствующий OPR), а затем игнорировать Chrome (хотя Opera совпадает с «Chrome»). Проблема с этим кодом заключается в том, что на этот раз Chrome будет проблемой (он будет обнаружен как Opera). Вы должны использовать более специфичный REGEX.

Тот факт, что некоторые браузеры частично подписаны как другие, связан с историей. Некоторые браузеры берут свой код от других, и поэтому они распознаются по-разному.