crossknowledge/devicedetect-bundle
Symfony bundle that integrates device detection into your application, identifying mobile, tablet, desktop, and other client types from the user agent. Provides configurable services for adapting responses, routing, and templates to the detected device.
composer require crossknowledge/devicedetect-bundle:^6.2
If you are pinned to twig/twig below 3.28, install ^6.1 instead or upgrade Twig as part of the same change.config/bundles.php:
CrossKnowledge\DeviceDetectBundle\CrossKnowledgeDeviceDetectBundle::class => ['all' => true],
config/packages/crossknowledge_device_detect.yaml:
cross_knowledge_device_detect:
user_agent: '%kernel.request%'
use CrossKnowledge\DeviceDetectBundle\DeviceDetector;
public function index(DeviceDetector $detector)
{
$device = $detector->detect();
return new Response('Detected: ' . $device->getClient('type'));
}
DeviceDetector: Main service for detection.Device: Holds parsed device data (OS, browser, etc.).ClientHint: For handling HTTP headers like Sec-CH-UA.6.2.0 is a dependency-only release. No public API, service id, config key, or Twig extension behaviour changed. Treat this as a Composer-resolution upgrade, not a code migration.
Inject DeviceDetector into controllers/services to parse the current request’s User-Agent:
public function show(DeviceDetector $detector, Request $request)
{
$device = $detector->detect($request->headers->get('User-Agent'));
$isMobile = $device->getClient('type') === 'mobile';
}
Cache detection results to avoid reprocessing the same User-Agent:
$cacheKey = 'device_' . md5($userAgent);
$device = $cache->get($cacheKey) ?? $detector->detect($userAgent);
$cache->set($cacheKey, $device, 3600); // Cache for 1 hour
Use detected data to modify responses (e.g., redirect mobile users to a different URL):
if ($device->getClient('type') === 'mobile') {
return redirect()->to('/mobile');
}
Leverage Sec-CH-UA headers for more accurate detection:
$clientHints = $request->headers->get('Sec-CH-UA');
$device = $detector->detect($userAgent, $clientHints);
Trigger actions based on device detection (e.g., logging or analytics):
// src/EventListener/DeviceListener.php
public function onKernelRequest(GetResponseEvent $event)
{
$device = $detector->detect($event->getRequest());
// Log or track device data
}
Register in services.yaml:
services:
App\EventListener\DeviceListener:
tags:
- { name: kernel.event_listener, event: kernel.request, method: onKernelRequest }
Pass the DeviceDetector to Twig templates:
# config/packages/twig.yaml
twig:
globals:
device_detector: '@cross_knowledge_device_detect.device_detector'
Use in templates:
{% if device_detector.detect(app.request).getClient('type') == 'mobile' %}
<link rel="stylesheet" href="{{ asset('css/mobile.css') }}">
{% endif %}
As of 6.2.0 the bundle's Twig constraint is ^2 | ^3.28. If your project already uses Twig as a global or as twig/twig directly, confirm the resolved version after composer update crossknowledge/devicedetect-bundle — a global registered with a signature that changed between Twig 2 and 3 (e.g. Twig\Extension\AbstractExtension) will silently break templates if you straddle both majors in a monorepo.
Include device data in API responses for analytics:
return $this->json([
'data' => $data,
'device' => [
'type' => $device->getClient('type'),
'os' => $device->getOs('name'),
'browser' => $device->getClient('name'),
],
]);
Mock the DeviceDetector in tests:
$mockDetector = $this->createMock(DeviceDetector::class);
$mockDetector->method('detect')->willReturn($mockDevice);
$this->container->set(DeviceDetector::class, $mockDetector);
twig/twig to ^2 | ^3.28). That means a project on Twig 3.0–3.27 cannot resolve ^6.2 without also bumping Twig.crossknowledge/devicedetect-bundle:^6.1 and defer.composer why twig/twig
composer update crossknowledge/devicedetect-bundle --with-dependencies --dry-run
twig/twig downgrade if another package (e.g. a Symfony form/translation bridge) still requires <3.28; Composer will prefer staying on 6.1 and you may not notice the bundle silently not upgrading.matomo/device-detector (last updated 2021), which may not include modern devices/browsers. 6.2.0 does not change this — the release is Twig-only, so detection accuracy is identical to 6.1.0.DeviceDetector rules or fork the package.User-Agent strings can be slow for high-traffic sites.mobiledetectlib.Sec-CH-UA headers are only supported in Chrome/Edge (since ~2021).User-Agent if Sec-CH-UA is missing.^3.28) indicates the maintained path is modern Twig 3, so treat Symfony 6.4/7.x with a current Twig as the well-tested combination and re-test rather than assuming Symfony 5 support is the target.$device->getClient('user_agent') to inspect raw input.composer show crossknowledge/devicedetect-bundle
composer show twig/twig
Version should read 6.2.x. If it reads 6.1.x after an update, Composer blocked the Twig constraint — see Pitfall 1.
Dump the full device object to debug:
$device = $detector->detect($request->headers->get('User-Agent'));
dump($device->getAll());
Output includes:
client: Browser/device info.os: Operating system.bot: Bot detection.If detection is inaccurate, update the rules in:
$detector->getParser()->setRules([/* custom rules */]);
(See matomo/device-detector for rule formats.)
Log problematic User-Agent strings for analysis:
if ($device->getClient('type') === 'unknown') {
\Log::warning('Unknown device: ' . $userAgent);
}
Extend detection logic by subclassing DeviceDetector:
class CustomDeviceDetector extends DeviceDetector
{
protected function getCustomRules()
{
return [
'custom_device' => '/CustomDevice\/1\.0/',
];
}
}
Register as a service:
services:
App\Service\CustomDeviceDetector:
decorates: 'cross_knowledge_device_detect.device_detector'
arguments: ['@App\Service\CustomDeviceDetector.inner']
Attach custom metadata to the Device object:
$device->setCustom('is_enterprise', true);
Replace the default detector entirely:
services:
cross_knowledge_device_detect.device_detector:
class: App\Service\MyCustomDetector
arguments: ['@service_container']
Decorators and overrides registered this way are unaffected by 6.2.0 — no service ids or constructor signatures changed.
By default, the bundle uses Symfony’s RequestStack. To use a custom source:
cross_knowledge_device_detect:
user_agent: 'app.request_stack' # Default
# OR
user_agent: '@custom.request_provider'
Skip parsing entirely (e.g., for performance):
cross_knowledge_device_detect:
enabled: false
Then manually instantiate DeviceDetector without auto-configuration.
The underlying matomo/device-detector supports multiple languages. Configure in PHP:
$detector->getParser()->setLanguage('en'); // Default
How can I help you explore Laravel packages today?