PHP 日本會議 2024

get_browser

(PHP 4, PHP 5, PHP 7, PHP 8)

get_browser判斷使用者瀏覽器的功能

描述

get_browser(?string $user_agent = null, bool $return_array = false): object|array|false

嘗試透過在 browscap.ini 檔案中查詢瀏覽器的資訊,判斷使用者瀏覽器的功能。

參數

user_agent

要分析的使用者代理。預設會使用 HTTP User-Agent 標頭的值;但是,您可以透過傳遞此參數來更改此值(即,查詢另一個瀏覽器的資訊)。

您可以使用 null 值來略過此參數。

return_array

如果設定為 true,此函式將會傳回 array 而不是 object

傳回值

資訊會以物件或陣列的形式傳回,其中包含代表各種資料元素的資料,例如,瀏覽器的主版本號碼和次版本號碼以及 ID 字串;針對諸如框架、JavaScript 和 Cookie 等功能,會傳回 true/false 值等等。

cookies 值僅表示瀏覽器本身能夠接受 Cookie,並不表示使用者已啟用瀏覽器接受 Cookie 或不接受。測試是否接受 Cookie 的唯一方法是使用 setcookie() 設定一個 Cookie,重新載入,並檢查該值。

當無法擷取任何資訊時,會傳回 false,例如,當 php.ini 中的 browscap 組態設定尚未設定時。

範例

範例 #1 列出有關使用者瀏覽器的所有資訊

<?php
echo $_SERVER['HTTP_USER_AGENT'] . "\n\n";

$browser = get_browser(null, true);
print_r($browser);
?>

以上範例將會輸出類似如下的內容

Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7) Gecko/20040803 Firefox/0.9.3

Array
(
    [browser_name_regex] => ^mozilla/5\.0 (windows; .; windows nt 5\.1; .*rv:.*) gecko/.* firefox/0\.9.*$
    [browser_name_pattern] => Mozilla/5.0 (Windows; ?; Windows NT 5.1; *rv:*) Gecko/* Firefox/0.9*
    [parent] => Firefox 0.9
    [platform] => WinXP
    [browser] => Firefox
    [version] => 0.9
    [majorver] => 0
    [minorver] => 9
    [cssversion] => 2
    [frames] => 1
    [iframes] => 1
    [tables] => 1
    [cookies] => 1
    [backgroundsounds] =>
    [vbscript] =>
    [javascript] => 1
    [javaapplets] => 1
    [activexcontrols] =>
    [cdf] =>
    [aol] =>
    [beta] => 1
    [win16] =>
    [crawler] =>
    [stripper] =>
    [wap] =>
    [netclr] =>
)

注意

注意:

為了使其運作,您的 php.ini 中的 browscap 組態設定必須指向您系統上 browscap.ini 檔案的正確位置。

browscap.ini 並未與 PHP 捆綁在一起,但您可以在這裡找到最新的 » php_browscap.ini 檔案。

雖然 browscap.ini 包含許多瀏覽器的資訊,但它仰賴使用者更新以保持資料庫為最新狀態。該檔案的格式相當不言自明。

新增筆記

使用者貢獻的筆記 17 則筆記

57
krozinov at gmail dot com
6 年前
在 PHP 7.0.15 和 7.1.1 及更高版本中,get_browser() 現在效能好得多 - 據報導快了 100 倍。變更記錄、錯誤描述和解決方案在這裡

https://php.dev.org.tw/ChangeLog-7.php(搜尋 get_browser())
https://bugs.php.net/bug.php?id=70490
https://github.com/php/php-src/pull/2242
68
匿名
8 年前
此函式對於當今的需求來說太慢了。

如果您需要瀏覽器/裝置/作業系統偵測,請嘗試此處列出的其中一個套件:https://github.com/ThaDafinser/UserAgentParser
41
Francesco R
8 年前
如果您只需要一個非常快速且簡單的函式來偵測瀏覽器名稱(更新至 2016 年 5 月)

<?php

function get_browser_name($user_agent)
{
if (
strpos($user_agent, 'Opera') || strpos($user_agent, 'OPR/')) return 'Opera';
elseif (
strpos($user_agent, 'Edge')) return 'Edge';
elseif (
strpos($user_agent, 'Chrome')) return 'Chrome';
elseif (
strpos($user_agent, 'Safari')) return 'Safari';
elseif (
strpos($user_agent, 'Firefox')) return 'Firefox';
elseif (
strpos($user_agent, 'MSIE') || strpos($user_agent, 'Trident/7')) return 'Internet Explorer';

return
'Other';
}

// 用法:

echo get_browser_name($_SERVER['HTTP_USER_AGENT']);

?>

此函式也解決了 Edge(在使用者代理中包含字串「Safari」和「Chrome」)、Chrome(包含字串「Safari」)和 IE11(不包含像所有其他 IE 版本那樣的「MSIE」)的問題。

請注意,「strpos」是檢查字串的最快函式(遠比「preg_match」更好),而 Opera + Edge + Chrome + Safari + Firefox + Internet Explorer 是當今最常用的瀏覽器(超過 97%)。
23
Konstantin Rozinov
6 年前
由於瀏覽器偵測可能很棘手且速度很慢,我比較了幾個套件。

http://thadafinser.github.io/UserAgentParserComparison/v5/index.html

https://github.com/sinergi/php-browser-detector
https://github.com/WhichBrowser/Parser-PHP
https://github.com/piwik/device-detector
https://php.dev.org.tw/manual/en/function.get-browser.php

以下為結果

使用者代理字串
Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.84 Safari/537.36

Sinergi 套件
---------------
在 Windows 10.0 上的 Chrome 63.0.3239.84
耗時 0.0022480487823486 秒。
---------------

WhichBrowser 套件
---------------
在 Windows 10 上的 Chrome 63
耗時 0.021045207977295 秒。
---------------

Piwik 套件
---------------
在 Windows 10 上的 Chrome 63.0
耗時 0.079447031021118 秒。
---------------

get_browser 套件
---------------
在 Windows 10 上的 Chrome 63.0
耗時 0.09611701965332 秒。
---------------

使用者代理字串
Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:57.0) Gecko/20100101 Firefox/57.0

Sinergi 套件
---------------
在 Windows 10.0 上的 Firefox 57.0
耗時 0.0023159980773926 秒。
---------------

WhichBrowser 套件
---------------
在 Windows 10 上的 Firefox 57.0
耗時 0.019663095474243 秒。
---------------

Piwik 套件
---------------
在 Windows 10 上的 Firefox 57.0
耗時 0.079678058624268 秒。
---------------

get_browser 套件
---------------
在 Windows 10 上的 Firefox 57.0
耗時 0.02236008644104 秒。
---------------

目前為止,在速度上(不一定是覆蓋率)始終勝出的是
https://github.com/sinergi/php-browser-detector
50
ruudrp at live dot nl
14 年前
令我驚訝的是,我發現沒有一個 get_browser 的替代方案輸出我使用 Opera 或 Chrome 時所尋找的正確名稱/版本組合。它們要么給出錯誤的名稱,例如實際上應該是 Chrome 的 Safari,如果 ua 字串包含版本號(如最新版本的 Chrome 和 Opera),則報告的數字是錯誤的。因此,我從各種示例中獲取了一些片段並將它們組合起來,並添加了版本檢查。

<?php
function getBrowser()
{
$u_agent = $_SERVER['HTTP_USER_AGENT'];
$bname = 'Unknown';
$platform = 'Unknown';
$version= "";

//首先取得平台?
if (preg_match('/linux/i', $u_agent)) {
$platform = 'linux';
}
elseif (
preg_match('/macintosh|mac os x/i', $u_agent)) {
$platform = 'mac';
}
elseif (
preg_match('/windows|win32/i', $u_agent)) {
$platform = 'windows';
}

// 接下來取得使用者代理的名稱,分開取得是有原因的
if(preg_match('/MSIE/i',$u_agent) && !preg_match('/Opera/i',$u_agent))
{
$bname = 'Internet Explorer';
$ub = "MSIE";
}
elseif(
preg_match('/Firefox/i',$u_agent))
{
$bname = 'Mozilla Firefox';
$ub = "Firefox";
}
elseif(
preg_match('/Chrome/i',$u_agent))
{
$bname = 'Google Chrome';
$ub = "Chrome";
}
elseif(
preg_match('/Safari/i',$u_agent))
{
$bname = 'Apple Safari';
$ub = "Safari";
}
elseif(
preg_match('/Opera/i',$u_agent))
{
$bname = 'Opera';
$ub = "Opera";
}
elseif(
preg_match('/Netscape/i',$u_agent))
{
$bname = 'Netscape';
$ub = "Netscape";
}

// 最後取得正確的版本號
$known = array('Version', $ub, 'other');
$pattern = '#(?<browser>' . join('|', $known) .
')[/ ]+(?<version>[0-9.|a-zA-Z.]*)#';
if (!
preg_match_all($pattern, $u_agent, $matches)) {
// 我們沒有匹配的數字,繼續
}

// 查看我們有多少個
$i = count($matches['browser']);
if (
$i != 1) {
//由於我們尚未使用「其他」參數,因此將有兩個
//查看版本是在名稱之前還是之後
if (strripos($u_agent,"Version") < strripos($u_agent,$ub)){
$version= $matches['version'][0];
}
else {
$version= $matches['version'][1];
}
}
else {
$version= $matches['version'][0];
}

// 檢查是否有數字
if ($version==null || $version=="") {$version="?";}

return array(
'userAgent' => $u_agent,
'name' => $bname,
'version' => $version,
'platform' => $platform,
'pattern' => $pattern
);
}

// 現在試試看
$ua=getBrowser();
$yourbrowser= "您的瀏覽器: " . $ua['name'] . " " . $ua['version'] . " 在 " .$ua['platform'] . " 回報: <br >" . $ua['userAgent'];
print_r($yourbrowser);
?>
16
Anonymous
5 年前
接續 Francesco R 於 2016 年的貼文。

他的函數適用於大多數人類流量;新增了一些行以涵蓋最常見的機器人流量。也修正了由於 strpos 行為導致函數無法偵測位置 0 的字串的問題。

<?php
// 函數編寫及測試於 2018 年 12 月
function get_browser_name($user_agent)
{
// 忽略大小寫。
$t = strtolower($user_agent);

// 如果字串 *開頭* 就是該字串,strpos 會返回 0 (即 FALSE)。使用一個蹩腳的技巧,在開頭加上一個空格。
// "[strpos()] 可能會返回布林值 FALSE,但也可能返回一個非布林值,其值會被評估為 FALSE。"
// https://php.dev.org.tw/manual/en/function.strpos.php
$t = " " . $t;

// 人類 / 一般使用者
if (strpos($t, 'opera' ) || strpos($t, 'opr/') ) return 'Opera' ;
elseif (
strpos($t, 'edge' ) ) return 'Edge' ;
elseif (
strpos($t, 'chrome' ) ) return 'Chrome' ;
elseif (
strpos($t, 'safari' ) ) return 'Safari' ;
elseif (
strpos($t, 'firefox' ) ) return 'Firefox' ;
elseif (
strpos($t, 'msie' ) || strpos($t, 'trident/7')) return 'Internet Explorer';

// 搜尋引擎
elseif (strpos($t, 'google' ) ) return '[機器人] Googlebot' ;
elseif (
strpos($t, 'bing' ) ) return '[機器人] Bingbot' ;
elseif (
strpos($t, 'slurp' ) ) return '[機器人] Yahoo! Slurp';
elseif (
strpos($t, 'duckduckgo') ) return '[機器人] DuckDuckBot' ;
elseif (
strpos($t, 'baidu' ) ) return '[機器人] Baidu' ;
elseif (
strpos($t, 'yandex' ) ) return '[機器人] Yandex' ;
elseif (
strpos($t, 'sogou' ) ) return '[機器人] Sogou' ;
elseif (
strpos($t, 'exabot' ) ) return '[機器人] Exabot' ;
elseif (
strpos($t, 'msn' ) ) return '[機器人] MSN' ;

// 常見工具和機器人
elseif (strpos($t, 'mj12bot' ) ) return '[機器人] Majestic' ;
elseif (
strpos($t, 'ahrefs' ) ) return '[機器人] Ahrefs' ;
elseif (
strpos($t, 'semrush' ) ) return '[機器人] SEMRush' ;
elseif (
strpos($t, 'rogerbot' ) || strpos($t, 'dotbot') ) return '[機器人] Moz 或 OpenSiteExplorer';
elseif (
strpos($t, 'frog' ) || strpos($t, 'screaming')) return '[機器人] Screaming Frog';

// 其他
elseif (strpos($t, 'facebook' ) ) return '[機器人] Facebook' ;
elseif (
strpos($t, 'pinterest' ) ) return '[機器人] Pinterest' ;

// 檢查機器人使用者代理中常用的字串
elseif (strpos($t, 'crawler' ) || strpos($t, 'api' ) ||
strpos($t, 'spider' ) || strpos($t, 'http' ) ||
strpos($t, 'bot' ) || strpos($t, 'archive') ||
strpos($t, 'info' ) || strpos($t, 'data' ) ) return '[機器人] 其他' ;

return
'其他 (未知)';
}
?>
這裡有更深入的文章
https://www.256kilobytes.com/content/show/1922/how-to-parse-a-user-agent-in-php-with-minimal-effort
18
The Digital Orchard
7 年前
好消息!最新版本的 PHP 針對此函數進行了效能修復。據報導,現在速度快了 100 倍。請參閱 ChangeLog 了解詳情。
5
tom at tgibbons dot com
2 年前
PHP cron 腳本,可自動更新 browscap.ini。它會比較版本號碼,以判斷是否需要更新

<?php
$eol
="\r\n"; //設定行尾 - cron

$fileurl = "https://browscap.org/stream?q=PHP_BrowsCapINI";
$verurl = "https://browscap.org/version-number";
$file = "/path/to/browscap.ini";

//尋找目前版本
$fp = fopen($file, "r+");
while ((
$line = stream_get_line($fp, 1024 * 1024, "\n")) !== false) {
if(
strpos($line,"Version=")===0) {
list(
$temp, $curver) = explode("=",$line);
break;
}
}
fclose($fp);
echo(
"目前的 browscap.ini 檔案版本: " . $curver);
//取得 browscap.org 目前版本
$newver = file_get_contents($verurl);
echo(
$eol . "新的 browscap.ini 檔案版本: " . $newver);
//如果新的版本可用,則更新
if($newver > $curver) {
if(
file_put_contents($file, file_get_contents($fileurl))) {
echo(
$eol . "browscap.ini 已更新!");
}
else {
echo(
$eol . "browscap.ini 更新失敗!");
}
}
else {
echo(
$eol . "browscap.ini 已是最新版本!");
}
echo(
$eol . "Cron 工作結束。" . $eol");
?>
6
Jeff Williams
6 年前
若要在 Linux 伺服器上自動更新 browscap.ini 檔案,您可以使用這個簡單的 shell 腳本

wget -O /etc/browscap.ini "http://browscap.org/stream?q=Full_PHP_BrowsCapINI"
chmod 664 /etc/browscap.ini

您可以將它放入通常位於 /etc/cron.weekly 中的每週 cron 工作資料夾,只是別忘了讓該腳本可執行 (chmod 775 scriptname)。
7
shashank
9 年前
由於 ruudrp 提供了程式碼 https://php.dev.org.tw/manual/en/function.get-browser.php#101125,,我加入了 Internet Explorer 11 的程式碼

<?php
function getBrowser()
{
$u_agent = $_SERVER['HTTP_USER_AGENT'];
$bname = 'Unknown';
$platform = 'Unknown';
$version= "";

//首先取得平台?
if (preg_match('/linux/i', $u_agent)) {
$platform = 'linux';
}
elseif (
preg_match('/macintosh|mac os x/i', $u_agent)) {
$platform = 'mac';
}
elseif (
preg_match('/windows|win32/i', $u_agent)) {
$platform = 'windows';
}

// 接著,取得 useragent 的名稱,是分開處理的,這是有原因的
if(preg_match('/MSIE/i',$u_agent) && !preg_match('/Opera/i',$u_agent))
{
$bname = 'Internet Explorer';
$ub = "MSIE";
}
elseif(
preg_match('/Trident/i',$u_agent))
{
// 此條件適用於 IE11
$bname = 'Internet Explorer';
$ub = "rv";
}
elseif(
preg_match('/Firefox/i',$u_agent))
{
$bname = 'Mozilla Firefox';
$ub = "Firefox";
}
elseif(
preg_match('/Chrome/i',$u_agent))
{
$bname = 'Google Chrome';
$ub = "Chrome";
}
elseif(
preg_match('/Safari/i',$u_agent))
{
$bname = 'Apple Safari';
$ub = "Safari";
}
elseif(
preg_match('/Opera/i',$u_agent))
{
$bname = 'Opera';
$ub = "Opera";
}
elseif(
preg_match('/Netscape/i',$u_agent))
{
$bname = 'Netscape';
$ub = "Netscape";
}

// 最後取得正確的版本號碼
// 增加了 "|:"
$known = array('Version', $ub, 'other');
$pattern = '#(?<browser>' . join('|', $known) .
')[/|: ]+(?<version>[0-9.|a-zA-Z.]*)#';
if (!
preg_match_all($pattern, $u_agent, $matches)) {
// 如果沒有匹配的號碼,則繼續執行
}

// 查看我們有多少個
$i = count($matches['browser']);
if (
$i != 1) {
// 我們會有兩個,因為我們還沒有使用 'other' 參數
// 查看版本號是在名稱之前還是之後
if (strripos($u_agent,"Version") < strripos($u_agent,$ub)){
$version= $matches['version'][0];
}
else {
$version= $matches['version'][1];
}
}
else {
$version= $matches['version'][0];
}

// 檢查是否有號碼
if ($version==null || $version=="") {$version="?";}

return array(
'userAgent' => $u_agent,
'name' => $bname,
'version' => $version,
'platform' => $platform,
'pattern' => $pattern
);
}

// 現在試試看
$ua=getBrowser();
$yourbrowser= "您的瀏覽器: " . $ua['name'] . " " . $ua['version'] . " 於 " .$ua['platform'] . " 報告: <br >" . $ua['userAgent'];
print_r($yourbrowser);
?>
9
tim at digicol dot de
10 年前
請注意,透過 php.ini 中的 browscap 設定載入 php_browscap.ini 可能會消耗大量的記憶體。目前版本的檔案大小有好幾 MB(即使是「精簡版」),並且可以在每個 PHP 處理程序中消耗數十 MB 的 RAM。即使您從未呼叫 get_browser(),也會發生這種情況,因為 php_browscap.ini 會在 PHP 啟動時載入。

如果您不使用 get_browser(),請務必將 php.ini 中的 browscap 設定留空 – 也許您只從 PHP 網頁呼叫它,而不是從 PHP CLI 程式碼呼叫。

我建議您比較載入和未載入 php_browscap.ini 時處理程序的記憶體消耗。如有必要,請考慮建立您自己的精簡版 php_browscap.ini 副本,其中只包含對您重要的瀏覽器。
6
Anonymous
13 年前
對於那些使用此函數來鎖定 MSIE 的人,更好的做法可能是使用 MSIE 特有的條件註解。更多資訊:<http://msdn.microsoft.com/en-us/library/ms537512%28VS.85%29.aspx>.

例如,表示您不理會使用 MSIE 6 或更早版本的用戶

<!--[if lt IE 7]>您似乎正在使用 <em>非常</em>舊版本的 MS Internet Explorer (MSIE)。如果您真的想繼續使用 MSIE,至少請<a href="http://www.microsoft.com/windows/internet-explorer/">升級</a>。<![endif]-->
2
mike at mike-griffiths dot co dot uk
17 年前
您不應該僅僅依賴此方法來解決跨瀏覽器相容性問題。良好的做法是加入 IE 樣式表的 HTML if 語句,以及動態檢查瀏覽器類型。
2
max at phpexpert dot de
20 年前
請注意,此函數會顯示特定瀏覽器可能可以顯示的內容,但不會顯示使用者已開啟/關閉的內容。

因此,即使使用者已關閉 JavaScript,此函數也可能會告訴您瀏覽器能夠執行 JavaScript。
0
Paxtez@example
3 個月前
請小心使用自行開發的版本。

例如,Francesco R 評價很高的版本 [ https://php.dev.org.tw/manual/en/function.get-browser.php#119332 ] 對於 Edge 來說已不再正確

目前的 Edge 報告的字串類似於
Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.0.0 Safari/537.36 Edg/127.0.0.0

請注意是 "Edg/xxx" 而不是 "Edge"

雖然將他的程式碼更新為以下內容是很簡單的

<?php
function get_browser_name($user_agent)
{
if (
strpos($user_agent, 'Opera') || strpos($user_agent, 'OPR/')) return 'Opera';
elseif (
strpos($user_agent, 'Edg')) return 'Edge';
elseif (
strpos($user_agent, 'Chrome')) return 'Chrome';
elseif (
strpos($user_agent, 'Safari')) return 'Safari';
elseif (
strpos($user_agent, 'Firefox')) return 'Firefox';
elseif (
strpos($user_agent, 'MSIE') || strpos($user_agent, 'Trident/7')) return 'Internet Explorer';
return
'Other';
}
?>

你永遠不知道未來數值何時會變更。
0
jeremie dot legrand at komori-chambon dot fr
8 年前
如果你在 php.ini 設定中使用「完整」的 Browscap INI 檔案要小心:我曾疑惑為什麼每個 Apache 執行緒在我的伺服器上會佔用 350MB 的 RAM,直到我將「完整」版本改為「精簡」版本(從 45MB 到 0.7MB)。

現在,每個執行緒只佔用 16MB...
所以如果這對你來說足夠,請使用精簡版本!
-2
zed
8 年前
為了完善 Francesco R 的內容,我加入了瀏覽器的版本。

function getNavigateur($user_agent)
{

if(empty($user_agent)) {
return array('nav' => 'NC', 'name' => 'NC', 'version' => 'NC');
}

$content_nav['name'] = 'Unknown';

if (strpos($user_agent, 'Opera') || strpos($user_agent, 'OPR/')) {

$content_nav['name'] = 'Opera';

if (strpos($user_agent, 'OPR/')) {
$content_nav['reel_name'] = 'OPR/';
} else {
$content_nav['reel_name'] = 'Opera';
}

}
elseif (strpos($user_agent, 'Edge')) {
$content_nav['name'] = $content_nav['reel_name'] = 'Edge';
}
elseif (strpos($user_agent, 'Chrome')) $content_nav['name'] = $content_nav['reel_name'] = 'Chrome';
elseif (strpos($user_agent, 'Safari')) $content_nav['name'] = $content_nav['reel_name'] = 'Safari';
elseif (strpos($user_agent, 'Firefox')) $content_nav['name'] = $content_nav['reel_name'] = 'Firefox';
elseif (strpos($user_agent, 'MSIE') || strpos($user_agent, 'Trident/7') || strpos($user_agent, 'Trident/7.0; rv:')) {
$content_nav['name'] = 'Internet Explorer';

if (strpos($user_agent, 'Trident/7.0; rv:')) {
$content_nav['reel_name'] = 'Trident/7.0; rv:';
} elseif (strpos($user_agent, 'Trident/7')) {
$content_nav['reel_name'] = 'Trident/7';
} else {
$content_nav['reel_name'] = 'Opera';
}

}

$pattern = '#' . $content_nav['reel_name'] . '\/*([0-9\.]*)#';

$matches = array();

if(preg_match($pattern, $user_agent, $matches)) {

$content_nav['version'] = $matches[1];
return $content_nav;

}

return array('name' => $content_nav['name'], 'version' => 'Inconnu');
}
To Top