piwik/device-detector
Parse User-Agent strings and Browser Client Hints to identify device type (desktop/tablet/mobile/TV/console, etc.), browser/client, operating system, and device brand/model. Universal PHP library from Matomo for accurate device detection.
Installation
composer require matomo/device-detector
Add to composer.json if using Laravel’s autoloader.
First Use Case Parse a User-Agent string in a Laravel controller or middleware:
use DeviceDetector\DeviceDetector;
use DeviceDetector\ClientHints;
$userAgent = request()->userAgent();
$clientHints = ClientHints::factory($_SERVER);
$dd = new DeviceDetector($userAgent, $clientHints);
$dd->parse();
// Example: Detect device type
if ($dd->isMobile()) {
return response()->json(['device' => 'mobile']);
}
Where to Look First
src/DeviceDetector.php: Core class methods.src/Parser/: Device, OS, and client parsers for granular control.Middleware for Device Detection Create a middleware to attach device data to requests:
namespace App\Http\Middleware;
use Closure;
use DeviceDetector\DeviceDetector;
use DeviceDetector\ClientHints;
class DetectDevice
{
public function handle($request, Closure $next)
{
$dd = new DeviceDetector($request->userAgent(), ClientHints::factory($_SERVER));
$dd->parse();
$request->merge([
'device' => $dd->getDeviceName(),
'is_mobile' => $dd->isMobile(),
'client' => $dd->getClient(),
]);
return $next($request);
}
}
Register in app/Http/Kernel.php:
protected $middleware = [
\App\Http\Middleware\DetectDevice::class,
];
Service Provider for Caching Configure caching (e.g., Laravel’s cache) in a service provider:
namespace App\Providers;
use DeviceDetector\DeviceDetector;
use DeviceDetector\Cache\LaravelCache;
use Illuminate\Support\ServiceProvider;
class DeviceDetectorServiceProvider extends ServiceProvider
{
public function register()
{
$this->app->singleton(DeviceDetector::class, function ($app) {
$dd = new DeviceDetector(request()->userAgent(), ClientHints::factory($_SERVER));
$dd->setCache(new LaravelCache());
return $dd;
});
}
}
Dynamic Conditional Logic Use detected data in views or controllers:
// Blade example
@if(request()->device === 'iPhone')
<link rel="stylesheet" href="{{ asset('css/ios.css') }}">
@endif
Accept-CH headers in your server (e.g., Nginx) for richer detection:
add_header Accept-CH "Sec-CH-UA, Sec-CH-UA-Mobile, Sec-CH-UA-Platform";
$dd->skipBotDetection(); // Faster but less accurate
12.3.4 instead of 12.3):
use DeviceDetector\Parser\Device\AbstractDeviceParser;
AbstractDeviceParser::setVersionTruncation(AbstractDeviceParser::VERSION_TRUNCATION_NONE);
Cache Invalidation
LaravelCache) may not invalidate stale entries. Clear cache manually if rules update:
cache()->forget('device-detector');
User-Agent Spoofing
if (strpos($userAgent, 'Mozilla/') === false) {
// Handle suspicious agents
}
Performance Overhead
$dd->setCache(new LaravelCache()); // Default is memory-only
Client Hints Unavailability
if (!$clientHints->has('Sec-CH-UA')) {
$dd->parseWithoutClientHints();
}
\Log::debug('DeviceDetector', [
'user_agent' => $userAgent,
'parsed' => $dd->getAll(),
]);
$dd = new DeviceDetector('Mozilla/5.0 (iPhone; CPU iPhone OS 15_0 like Mac OS X) ...');
Custom Rules
Extend parsers by overriding YAML rules (e.g., src/Parser/Device/DeviceParser.php):
# Add to `device-detector/data/device.yaml`
Samsung Galaxy S23:
pattern: Samsung Galaxy S23
is_tablet: false
PSR-6 Cache Adapter
For advanced caching, implement DeviceDetector\Cache\CacheInterface:
class RedisCache implements CacheInterface {
public function get($key) { /* ... */ }
public function set($key, $value, $ttl = null) { /* ... */ }
}
Bot Whitelisting Override bot detection logic:
$dd->setBotParser(new CustomBotParser());
session()->put('device', $dd->getAll());
public function scopeMobile($query)
{
return $query->whereHas('user', fn($q) => $q->where('device', 'like', '%mobile%'));
}
return response()->json([
'data' => $model,
'meta' => [
'device' => request()->device,
'is_mobile' => request()->is_mobile,
],
]);
How can I help you explore Laravel packages today?