├── LICENSE.md ├── README.md ├── composer.json ├── config └── device-detector.php ├── phpstan.neon ├── pint.json └── src ├── CacheRepository.php ├── Device.php ├── DeviceDetector.php └── DeviceDetectorServiceProvider.php /LICENSE.md: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) Rifki Aria Gumelar 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Laravel Device Detector 2 | === 3 | 4 | [![tests](https://github.com/reefki/laravel-device-detector/actions/workflows/tests.yml/badge.svg)](https://github.com/reefki/laravel-device-detector/actions/workflows/tests.yml) 5 | 6 | The Laravel wrapper for [Matomo Universal Device Detection](https://github.com/matomo-org/device-detector) library seamlessly integrates device detection capabilities into Laravel applications. 7 | 8 | ## Installation 9 | 10 | This package can be installed through Composer. 11 | 12 | ```bash 13 | composer require reefki/laravel-device-detector 14 | ``` 15 | 16 | Optionally, you can publish the config file of this package with this command: 17 | 18 | ```bash 19 | php artisan vendor:publish --provider="Reefki\DeviceDetector\DeviceDetectorServiceProvider" --tag="config" 20 | ``` 21 | 22 | ## Usage 23 | Detect device from a user agent string: 24 | 25 | ```php 26 | use Reefki\DeviceDetector\Device; 27 | 28 | $device = Device::detect($request->userAgent()); 29 | ``` 30 | 31 | Detect device from a user agent string and optional hints: 32 | 33 | ```php 34 | use Reefki\DeviceDetector\Device; 35 | 36 | $device = Device::detect($request->userAgent(), $request->server()); 37 | ``` 38 | 39 | Detect device from a request instance: 40 | 41 | ```php 42 | use Reefki\DeviceDetector\Device; 43 | 44 | $device = Device::detectRequest($request); 45 | ``` 46 | 47 | Detect device directly from a request instance: 48 | 49 | ```php 50 | $device = $request->device(); 51 | ``` 52 | 53 | All of the above methods wil return a `DeviceDetector\DeviceDetector` instance which you can use to get the information about the device: 54 | 55 | ```php 56 | if ($device->isBot()) { 57 | $botInfo = $device->getBot(); 58 | } else { 59 | $clientInfo = $device->getClient(); 60 | $osInfo = $device->getOs(); 61 | $device = $device->getDeviceName(); 62 | $brand = $device->getBrandName(); 63 | $model = $device->getModel(); 64 | } 65 | ``` 66 | 67 | Read the [Matomo's Universal Device Detection](https://github.com/matomo-org/device-detector/blob/master/README.md) library readme for more information on how to use the returned instance. 68 | 69 | ## Testing 70 | 71 | Run the tests with: 72 | 73 | ``` bash 74 | vendor/bin/phpunit 75 | ``` 76 | 77 | ## Credits 78 | 79 | - [Matomo Universal Device Detection](https://github.com/matomo-org/device-detector) 80 | - [All Contributors](../../contributors) 81 | 82 | ## License 83 | 84 | The MIT License (MIT). Please see [License File](LICENSE.md) for more information. 85 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "reefki/laravel-device-detector", 3 | "description": "Laravel wrapper for Matomo's Universal Device Detection library.", 4 | "type": "library", 5 | "license": "MIT", 6 | "authors": [ 7 | { 8 | "name": "Rifki Aria Gumelar", 9 | "email": "rifki@rifki.net" 10 | } 11 | ], 12 | "require": { 13 | "laravel/framework": "^9.0|^10.0|^11.0|^12.0", 14 | "matomo/device-detector": "^6.0" 15 | }, 16 | "require-dev": { 17 | "orchestra/testbench": "^7.0|^8.0", 18 | "phpunit/phpunit": "^10.0", 19 | "laravel/pint": "^1.13", 20 | "phpstan/phpstan": "^1.10" 21 | }, 22 | "autoload": { 23 | "psr-4": { 24 | "Reefki\\DeviceDetector\\": "src/" 25 | } 26 | }, 27 | "autoload-dev": { 28 | "psr-4": { 29 | "Reefki\\DeviceDetector\\Tests\\": "tests/" 30 | } 31 | }, 32 | "extra": { 33 | "laravel": { 34 | "providers": [ 35 | "Reefki\\DeviceDetector\\DeviceDetectorServiceProvider" 36 | ], 37 | "aliases": { 38 | "Device": "Reefki\\DeviceDetector\\Device" 39 | } 40 | } 41 | }, 42 | "scripts": { 43 | "test": "vendor/bin/phpunit", 44 | "ftest": "vendor/bin/phpunit --filter" 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /config/device-detector.php: -------------------------------------------------------------------------------- 1 | env('DEVICE_DETECTOR_CACHE_STORE'), 5 | ]; 6 | -------------------------------------------------------------------------------- /phpstan.neon: -------------------------------------------------------------------------------- 1 | parameters: 2 | level: 9 3 | 4 | paths: 5 | - src 6 | -------------------------------------------------------------------------------- /pint.json: -------------------------------------------------------------------------------- 1 | { 2 | "preset": "psr12" 3 | } 4 | -------------------------------------------------------------------------------- /src/CacheRepository.php: -------------------------------------------------------------------------------- 1 | cache->get($id); 30 | } 31 | 32 | /** 33 | * Determine if an item exists in the cache. 34 | * 35 | * @param string $id 36 | * @return bool 37 | */ 38 | public function contains(string $id): bool 39 | { 40 | return $this->cache->has($id); 41 | } 42 | 43 | /** 44 | * Store an item in the cache. 45 | * 46 | * @param string $id 47 | * @param mixed $data 48 | * @param int $lifeTime 49 | * @return bool 50 | */ 51 | public function save(string $id, mixed $data, int $lifeTime = 3600): bool 52 | { 53 | return $this->cache->put($id, $data, $lifeTime); 54 | } 55 | 56 | /** 57 | * Remove an item from the cache. 58 | * 59 | * @param string $id 60 | * @return bool 61 | */ 62 | public function delete(string $id): bool 63 | { 64 | return $this->cache->forget($id); 65 | } 66 | 67 | /** 68 | * Remove all items from the cache. 69 | * 70 | * @return bool 71 | */ 72 | public function flushAll(): bool 73 | { 74 | return $this->cache->flush(); 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /src/Device.php: -------------------------------------------------------------------------------- 1 | $headers 27 | * @return \DeviceDetector\DeviceDetector 28 | */ 29 | public function detect(string $userAgent, array $headers = []): MatomoDeviceDetector 30 | { 31 | $clientHints = ClientHints::factory( 32 | headers: $headers, 33 | ); 34 | 35 | $detector = new MatomoDeviceDetector( 36 | userAgent: $userAgent, 37 | clientHints: $clientHints, 38 | ); 39 | 40 | $detector->setCache( 41 | cache: $this->cache, 42 | ); 43 | 44 | $detector->parse(); 45 | 46 | return $detector; 47 | } 48 | 49 | /** 50 | * Detect the device for the given request. 51 | * 52 | * @param \Illuminate\Http\Request $request 53 | * @return \DeviceDetector\DeviceDetector 54 | */ 55 | public function detectRequest(Request $request): MatomoDeviceDetector 56 | { 57 | return $this->detect( 58 | userAgent: $request->userAgent() ?? '', 59 | headers: (array) $request->server(), 60 | ); 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /src/DeviceDetectorServiceProvider.php: -------------------------------------------------------------------------------- 1 | app->when(CacheRepository::class) 19 | ->needs(Repository::class) 20 | ->give(fn ($app) => $app->cache->store( 21 | $app->config->get('device-detector.cache_store') 22 | )); 23 | } 24 | 25 | /** 26 | * Bootstrap services. 27 | * 28 | * @return void 29 | */ 30 | public function boot(): void 31 | { 32 | $this->mergeConfigFrom(__DIR__.'/../config/device-detector.php', 'device-detector'); 33 | 34 | if ($this->app->runningInConsole()) { 35 | $this->publishes([ 36 | __DIR__.'/../config/device-detector.php' => config_path('device-detector.php'), 37 | ], 'config'); 38 | } 39 | 40 | $this->app->singleton(DeviceDetector::class, DeviceDetector::class); 41 | 42 | Request::macro('device', function () { 43 | /** @var \Illuminate\Http\Request $this */ 44 | /** @phpstan-ignore-next-line */ 45 | return app(DeviceDetector::class)->detectRequest($this); 46 | }); 47 | } 48 | } 49 | --------------------------------------------------------------------------------