需要完成获取请求手机品牌、型号的功能,类似微博的显示:

微博显示发布的设备品牌、型号

网上找了一个 DeviceDetector,看最近新版更新时间是最近 6 月 6 日。支持 composer 安装,调用方法也简单。之所以关注更新时间,是因为手机每年都会有新的型号上市。如果长期不更新,则会匹配不到新出的手机。

The Universal Device Detection library will parse any User Agent and detect the browser, operating system, device used (desktop, tablet, mobile, tv, cars, console, etc.), brand and model.

简介里提到可以解析任何的 User Agent,检测浏览器、操作系统、使用设备、品牌和型号。

之后又找到一个型号和对应手机的匹配表 zol-collector,复制其中的 insert 语句,替换 table 名称,定义两个字段 modelmobile 的手机型号表,然后执行插入到数据库中。

laravel 匹配查询:

$model = MobileModel::whereRaw("'$userAgent' like CONCAT('%',model,'%')")->first();

两个都是比较新的,DeviceDetector 是使用规则匹配,zol-collector 则需要通过 SQL 语句匹配。zol-collector 有个好处就是,可以显示成中文,可以手动编辑手机名称。所以优先数据库匹配,匹配不到则使用规则匹配。

使用 华为 Mate40 Pro 手机的 User Agent 解析:

  • 数据库匹配结果:华为Mate 40 Pro 5G (8GB+256GB)
  • 规则匹配结果:Huawei NOH-AN01
    function getMobileType($userAgent = '')
    {
        $dd = new DeviceDetector($userAgent);
        $dd->parse();
        if ($dd->isBot()) {
            return 'robot';
        } else {
            $mobileModel = \App\Models\Customer\MobileModel::whereRaw("'$userAgent' like CONCAT('%',model,'%')")->first();
            Log::info("[helpers][getMobileType] mobileModel:" . ($mobileModel ? json_encode($mobileModel->toArray()) : 'null'));
            if (is_null($mobileModel)) {
                $brand = $dd->getBrandName();
                $model = $dd->getModel();
                $device_name = $dd->getDeviceName();
                $device = $dd->getDevice();
                Log::info("[helpers][getMobileType] brand:" . $brand . ',model:' . $model . ',device_name:' . $device_name . ',device:' . $device);
                return $brand . ' ' . $model;
            } else {
                return $mobileModel->mobile;
            }
        }
    }

测试了华为 Mate40 Pro华为 P30,还有一台 iphone XS Max,前面的两个华为手机数据库查询到记录,但苹果手机匹配结果: Apple iphone。也就是说没有匹配到苹果手机具体型号。

查询了这台苹果手机的 User Agent

Mozilla/5.0 (iPhone; CPU iPhone OS 15_7_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 MicroMessenger/8.0.39(0x18002730) NetType/WIFI Language/zh_CN

确实没有找到型号,其中的 15_7_1 是系统版本。找了

iPhone 7 displays as "iPhone" #5860
Detect Apple iPhone Model Numbers and User-Agents
Device Detection for Apple iPhone and iPad
Why is the exact model of iPhones not available?

几篇博文,里面提到苹果手机模糊了设备信息,没有提供型号标识符。其中 Device Detection for Apple iPhone and iPad 提供了根据几个方面判断苹果手机型号方法,比较有参考价值的是 Screen dimensions and pixel density,即 设备像素比屏幕宽度、高度。但这些信息后台 php 是获取不到的,需要前端 js 获取判断。

所以,php 根据 User Agent 获取苹果手机型号,有一定的局限性。

跟前端提了一下,前端说小程序有接口可以直接获取到设备型号。找了一下,my.getSystemInfo - 支付宝小程序wx.getSystemInfo(Object object) - 微信小程序。其中支付宝小程序获取系统信息的接口有一个体验二维码,测试页面如下:

支付宝小程序获取设备信息

可以看到前端获取到的与实际想要的结果也有一定的差距,它是品牌+型号,但这个型号完全不知道对应的是什么手机。

目前来说,php 的两种方法叠加起来,够用就行。