Weave Code
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

Parser Laravel Package

whichbrowser/parser

PHP user-agent parser for browser sniffing (use sparingly). WhichBrowser/Parser identifies browser, engine, OS and device with names and versions. Works on PHP 7.0+ including PHP 8; useful for analytics or UX edge cases.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation

    composer require whichbrowser/parser
    

    Add to composer.json if not auto-loaded:

    "autoload": {
        "psr-4": {
            "App\\": "app/",
            "WhichBrowser\\Parser\\": "vendor/whichbrowser/parser/src/"
        }
    }
    

    Run composer dump-autoload.

  2. First Use Case Parse a user-agent string in a controller or middleware:

    use WhichBrowser\Parser\Parser;
    
    $parser = new Parser();
    $browser = $parser->parse($_SERVER['HTTP_USER_AGENT'] ?? '');
    
    // Outputs something like: "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36"
    echo $browser->getBrowserName(); // "Chrome"
    echo $browser->getVersion();    // "120.0.0.0"
    
  3. Where to Look First

    • Documentation: GitHub README (minimal but clear).
    • Source Code: Focus on src/WhichBrowser/Parser/Parser.php for core logic.
    • Tests: tests/ directory for edge cases (e.g., malformed user-agents).

Implementation Patterns

Common Workflows

1. Middleware for Browser Detection

Attach to Laravel’s middleware stack to enrich requests:

namespace App\Http\Middleware;

use WhichBrowser\Parser\Parser;
use Closure;

class DetectBrowser
{
    public function handle($request, Closure $next)
    {
        $parser = new Parser();
        $browser = $parser->parse($request->userAgent());

        $request->merge([
            'browser' => $browser->getBrowserName(),
            'browser_version' => $browser->getVersion(),
            'is_mobile' => $browser->isMobile(),
            'is_bot' => $browser->isBot(),
        ]);

        return $next($request);
    }
}

Register in app/Http/Kernel.php:

protected $middleware = [
    \App\Http\Middleware\DetectBrowser::class,
];

2. Conditional Logic in Views/Blades

Use the parsed data to serve tailored content:

@if($request->browser === 'Safari' && $request->browser_version < 15)
    <script>
        alert('Please upgrade Safari for full functionality.');
    </script>
@endif

3. Caching Parsed Results

Avoid reprocessing the same user-agent repeatedly (e.g., in APIs):

$cacheKey = 'browser_'.md5($userAgent);
$browser = cache()->remember($cacheKey, now()->addHours(1), function() use ($userAgent) {
    return (new Parser())->parse($userAgent);
});

4. Integration with Laravel Scout

Filter search results by browser:

$results = Product::search('laptop')->browser('Chrome')->get();

Requires a custom Scout extension (see Extension Points below).


Integration Tips

Laravel Service Provider

Bind the parser as a singleton for dependency injection:

namespace App\Providers;

use WhichBrowser\Parser\Parser;
use Illuminate\Support\ServiceProvider;

class BrowserServiceProvider extends ServiceProvider
{
    public function register()
    {
        $this->app->singleton(Parser::class, function () {
            return new Parser();
        });
    }
}

Use in controllers:

use WhichBrowser\Parser\Parser;

public function __construct(Parser $parser) {
    $this->parser = $parser;
}

API Responses

Include browser info in API responses:

return response()->json([
    'data' => $product,
    'metadata' => [
        'browser' => $request->browser,
        'is_mobile' => $request->is_mobile,
    ],
]);

Analytics Tracking

Log browser data to a third-party service (e.g., Mixpanel, Google Analytics):

$analytics->track('Browser Visit', [
    'browser' => $browser->getBrowserName(),
    'version' => $browser->getVersion(),
    'device' => $browser->isMobile() ? 'mobile' : 'desktop',
]);

Gotchas and Tips

Pitfalls

1. False Positives in Bot Detection

  • The isBot() method may misclassify legitimate crawlers (e.g., Googlebot).
  • Fix: Whitelist known bots or combine with a dedicated bot-detection library like botlib/botlib.

2. Performance with High Traffic

  • Parsing user-agents on every request can be costly for high-traffic apps.
  • Fix: Cache results aggressively (see Caching Parsed Results above) or use a reverse proxy (e.g., Nginx) to extract browser data before it reaches PHP.

3. Edge Cases in User-Agent Strings

  • Malformed or obfuscated user-agents (e.g., from bots or privacy tools) may return incomplete data.
  • Fix: Fallback to defaults or log unusual patterns:
    try {
        $browser = $parser->parse($userAgent);
    } catch (\Exception $e) {
        $browser = new \WhichBrowser\Parser\Browser();
        \Log::warning("Failed to parse user-agent: {$userAgent}", ['error' => $e]);
    }
    

4. Version Parsing Quirks

  • Some browsers (e.g., Chrome on iOS) report Safari versions due to WebKit.
  • Fix: Use getBrowserFamily() for broader categorization:
    $browser->getBrowserFamily(); // "Blink" for Chrome, "WebKit" for Safari
    

Debugging

Inspect Raw Data

Dump the full parsed object to debug:

dd($browser->toArray());

Output includes:

[
    'browser' => 'Chrome',
    'version' => '120.0.0.0',
    'os' => 'Windows',
    'device' => 'desktop',
    'is_mobile' => false,
    'is_bot' => false,
    // ... and more
]

Update Database

The package uses a static database of user-agent patterns. To update:

composer require whichbrowser/parser:dev-main

Or manually pull updates from the GitHub repo.


Extension Points

1. Custom Browser Rules

Extend the parser to handle proprietary or niche user-agents:

$parser = new Parser();
$parser->addRule('MyCustomBrowser', '/MyCustomBrowser\/(\d+\.\d+)/');
$browser = $parser->parse('MyCustomBrowser/1.2.3');
echo $browser->getBrowserName(); // "MyCustomBrowser"

2. Laravel Scout Extensions

Add browser-based filtering to Scout:

namespace App\Scout;

use WhichBrowser\Parser\Parser;
use Laravel\Scout\Builder;

class BrowserExtensions
{
    public function extend(Builder $builder)
    {
        $builder->macro('browser', function ($browserName) use ($builder) {
            $parser = app(Parser::class);
            $userAgent = $builder->query->get('user_agent');
            $browser = $parser->parse($userAgent);
            return $builder->where('browser', $browserName);
        });
    }
}

Register in AppServiceProvider:

\App\Scout\BrowserExtensions::extend(app('scout'));

3. Event Listeners

Trigger actions based on browser detection:

namespace App\Listeners;

use WhichBrowser\Parser\Browser;

class LogBrowserEvent
{
    public function handle($event)
    {
        $browser = $event->browser;
        if ($browser->getBrowserName() === 'Firefox') {
            \Log::info("Firefox user detected", ['version' => $browser->getVersion()]);
        }
    }
}

Dispatch in middleware:

event(new \App\Events\BrowserDetected($browser));

Configuration Quirks

Disable Updates

The parser checks for updates on initialization. Disable with:

$parser = new Parser();
$parser->setUpdateCheck(false);

**Custom Data Directory

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.
besmartand-pro/php-quality-config
sentix/ai-chatbot
terminal42/code-quality-tools
codifyo/ts-generator-bundle
testo/fiber
mintobit/jobqueue
a4sex/maintenance-bundle
a4sex/entity-date-update
a4sex/client-identifier
a4sex/base-utilites
a4sex/key-value-storage
a4sex/micro-status
chilldev/dependency-injection-extra
datinglibre/datinglibre-app-api
biberltd/corebundle
bricre/symfony-bundle-test
biberltd/logbundle
dominium/http-adapter-bundle
dominium/google-analytics
a4sex/auto-clean-entity