Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Mobile Detect Light Bundle Laravel Package

thormeier/mobile-detect-light-bundle

Symfony bundle integrating the lightweight MobileDetect library, providing a simple service to detect mobile devices, tablets, and bots so you can serve device-aware responses without pulling in heavy dependencies.

View on GitHub
Deep Wiki
Context7

Getting Started

What this actually is. A thin Symfony 2 bundle that does two things: registers mobiledetect/mobiledetectlib (Mobile_Detect) as a container service, and exposes it to Twig. There is no admin UI, no config tree, no Doctrine, no routing — it is a ~100-line glue package. Treat the bundle as documentation of a pattern rather than a dependency you build on.

Install (Symfony 2.x only).

composer require thormeier/mobile-detect-light-bundle
// app/AppKernel.php
public function registerBundles()
{
    $bundles = array(
        // ...
        new Thormeier\MobileDetectLightBundle\ThormeierMobileDetectLightBundle(),
    );
}

Where to look first, in this order:

  1. Resources/config/services.yml — this is the whole integration surface. Note the service id (typically thormeier.mobile_detect / mobile_detect) and whether the Twig extension is registered unconditionally or behind a tag.
  2. Twig/ — the extension class tells you the exact function names (is_mobile, is_tablet, …). Do not guess these; run php app/console container:debug | grep -i mobile and php app/console container:debug twig.extension to confirm.
  3. DependencyInjection/ — confirms there is (or isn't) a configuration node you can override.

First use case — device-conditional markup in a template, without touching PHP:

{# app/Resources/views/layout.html.twig #}
{% if is_mobile() and not is_tablet() %}
    {% include 'AcmeBundle:Layout:mobile.html.twig' %}
{% else %}
    {% include 'AcmeBundle:Layout:desktop.html.twig' %}
{% endif %}

That is the 80% use case: branch a layout or include a heavier/leaner partial. Everything below is about doing it without painting yourself into a corner.

Implementation Patterns

1. Gate at the layout boundary, not in every template. One {% if %} in the base layout that selects a partial is maintainable; is_mobile() sprinkled across fifty templates is not. Keep a single "device class" concept.

{# base.html.twig #}
{% set device = is_tablet() ? 'tablet' : (is_mobile() ? 'phone' : 'desktop') %}
{% include 'AcmeBundle:Layout:' ~ device ~ '.html.twig' %}

2. Normalise device class once per request in a kernel listener. Better than calling the detector from many places, and it gives you a single seam to swap in a different detector later.

// Acme\Bundle\AppBundle\EventListener\DeviceListener.php
class DeviceListener
{
    private $detect;

    public function __construct(\Mobile_Detect $detect)
    {
        $this->detect = $detect;
    }

    public function onKernelRequest(GetResponseEvent $event)
    {
        $request = $event->getRequest();
        $request->attributes->set('device_class', $this->resolve());
    }

    private function resolve()
    {
        if ($this->detect->isTablet()) {
            return 'tablet';
        }

        return $this->detect->isMobile() ? 'phone' : 'desktop';
    }
}

Then expose it as a Twig global (twig.globals.device_class) via config.yml, so templates never call the detector directly.

3. Controller/service usage when you need to act, not just render. Typical real uses: redirect to an m. subdomain, pick a lighter pagination size, disable a heavy widget, choose a different cache TTL.

public function indexAction()
{
    if ($this->get('mobile_detect')->isMobile() && !$this->get('mobile_detect')->isTablet()) {
        return $this->redirect($this->generateUrl('mobile_home'));
    }
    // ...
}

Always verify the service id against container:debug — this bundle's id has changed across its (few) releases.

4. Cache the verdict, keyed on the UA. Mobile_Detect is a pile of regexes run against a string; it is cheap but not free, and you do not need to re-derive it per request. In Symfony, a small memoising decorator around the detector (or storing the class in the session at first hit) is enough. The important rule is the next one.

5. Set Vary: User-Agent whenever the response body depends on device class. If you branch templates on UA, any HTTP cache between you and the user — Symfony's HttpCache, Varnish, a CDN — will otherwise serve a desktop layout to phones. This is the single most common production failure with UA-based rendering.

$response->setVary('User-Agent');
$response->setPublic();
$response->setMaxAge(600);

6. Prefer CSS/JS feature detection for anything functional. Use this bundle for payload decisions (image size, partial to include, redirect target), not for capability decisions (touch, viewport, WebGL). Modern practice is responsive CSS + matchMedia; UA sniffing is a fallback.

7. Integration tip for Laravel developers (the honest translation, since this package is not Laravel-compatible): skip the bundle and bind the underlying library directly. Three lines in a service provider reproduces 100% of its value.

// app/Providers/MobileDetectServiceProvider.php
$this->app->singleton(\Mobile_Detect::class, function () {
    return new \Mobile_Detect($_SERVER['HTTP_USER_AGENT'] ?? null);
});

// Blade directive
Blade::directive('mobile', fn () => "<?php if (app(\\Mobile_Detect::class)->isMobile()): ?>");
Blade::directive('endmobile', fn () => "<?php endif; ?>");

If you want a maintained, Laravel-native equivalent with the same behaviour plus a facade and parser abstraction, jenssegers/agent is the drop-in successor in spirit.

Gotchas and Tips

  • Symfony 2 only, and Symfony 2 is EOL. No services.yaml, no autowiring, no autoconfiguration, no Symfony 3/4/5/6 compatibility. Two stars, zero dependents. If you are on anything ≥ Symfony 3, this bundle is not an option — register mobiledetect/mobiledetectlib yourself.

  • No configuration means no override hook. Because the bundle ships no config tree, you cannot pass a custom UA or headers from config.yml. Override the service definition in your app's services.yml (same id, later file wins) or add a compiler pass. This also means you cannot swap the detector class without overriding the definition.

  • isMobile() returns true for tablets. This trips up nearly everyone. Always test isTablet() first, or use isMobile() && !isTablet().

  • CLI, queue workers and tests have no $_SERVER['HTTP_USER_AGENT']. Mobile_Detect then falls back to an empty UA and reports "desktop" for everything. If you ever use the detector outside an HTTP request, construct it with an explicit UA string rather than relying on the default constructor argument.

  • Spoofable and increasingly unreliable. UA strings are user-controlled and frozen by browsers (Chrome reduction, iOS "Request Desktop Site"). Never gate security, pricing or A/B assignment on device class. Never throw away functionality a user might need — render a fallback, don't hide content permanently.

  • Twig function-name collisions. If another bundle registers is_mobile, the last-loaded extension wins silently. container:debug twig.extension is the fastest way to see who registered what.

  • Watch out for double instantiation. The Twig extension and your controller may get different instances; with a heavy Mobile_Detect subclass this can matter. Make the service shared (default) and don't new Mobile_Detect() inline anywhere.

  • Debugging the verdict. When detection seems wrong, dump the raw input before the logic: $detect->getUserAgent() and $detect->getScriptVersion(). getScriptVersion() tells you which library release produced the result — useful when a new browser is misclassified and you need to pin/bump the library rather than the bundle.

  • The bundle pins an old mobiledetectlib. Because it was written in the Symfony 2 era, its composer.json constrains the library to a 2.x-era version whose UA database is years stale. You can usually relax this by adding "mobiledetect/mobiledetectlib": "^2.9" explicitly to your root composer.json, but be prepared for conflicts.

  • Extension point to prefer: decorate the Twig extension or wrap the service in your own DeviceResolver class, and let the bundle's service be a pure adapter. When you eventually remove the bundle (likely), only one small class changes.

  • Migration path off the bundle: composer remove thormeier/mobile-detect-light-bundle, then define the service yourself —

    services:
        mobile_detect:
            class: Mobile_Detect
        app.twig.mobile_detect:
            class: Acme\Twig\MobileDetectExtension
            arguments: ['@mobile_detect']
            tags: [{ name: twig.extension }]
    

    That is functionally identical to what the bundle does, and it is ~10 lines you now own and can keep current.

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
socialdept/atp-orm
cboxdk/laravel-assistant-client
socialdept/atp-resolver
socialdept/tenant-domains
tautvydasr/blade-class-names
socialdept/color-scales
maherelgamil/controller
coleus/widgets
coleus/table
coleus/users
coleus/music
coleus/health
coleus/calendar
coleus/notes
coleus/support
coleus/settings
coleus/apps
seampact/laravel
emmyconceptng/laravel-ng-postcode
jjsquady/round-robin