When using this package with Laravel 13, the parse() method in hisorange\BrowserDetect\Parser can return __PHP_Incomplete_Class instead of a ResultInterface object when the result is retrieved from cache. This causes a fatal type error.
Steps to Reproduce
The following code demonstrates the issue by parsing a user agent string twice (first call creates cache, second call retrieves from cache):
use hisorange\BrowserDetect\Parser;
use Illuminate\Support\Facades\Cache;
$userAgent = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36';
$parser = new Parser(
Cache::store('file'),
request(),
config('browser-detect')
);
// First call - parses and stores in cache
$result1 = $parser->parse($userAgent);
echo 'Browser Name: ' . $result1->browserName() . "\n";
// Second call - retrieves from cache and fails
$result2 = $parser->parse($userAgent);
echo 'Browser Name: ' . $result2->browserName() . "\n";
Expected Output
Browser Name: Chrome 120
Browser Name: Chrome 120
Actual Output
hisorange\BrowserDetect\Parser::parse(): Return value must be of type hisorange\BrowserDetect\Contracts\ResultInterface, __PHP_Incomplete_Class returned
at vendor/hisorange/browser-detect/src/Parser.php:172
168▕
169▕ $this->runtime[$key] = $result;
170▕ }
171▕
➜ 172▕ return $this->runtime[$key];
173▕ }
174▕
175▕ /**
176▕ * Create a unique cache key for the user agent.
Root Cause
Laravel 13 introduced a security feature that requires a whitelist of classes that can be unserialized from cache. This prevents arbitrary class deserialization vulnerabilities. See the Laravel 13 upgrade guide for details.
When hisorange\BrowserDetect\Result is not in the whitelist, Laravel's cache system cannot reconstruct the object during unserialization, resulting in __PHP_Incomplete_Class.
Solution
Add the Result class to the serializable_classes array in your config/cache.php file:
return [
// ... other cache configuration
/*
|--------------------------------------------------------------------------
| Serializable Classes
|--------------------------------------------------------------------------
|
| Here you may specify which classes may be unserialized. This prevents
| PHP from unserializing arbitrary objects. You may use "*" to allow all.
|
*/
'serializable_classes' => [
\hisorange\BrowserDetect\Result::class,
],
];
Alternatively, if you trust all cached data, you can use:
'serializable_classes' => true, // Not recommended!
Note: After updating the configuration, clear your cache:
Documentation Suggestion
It would be helpful to add a note about Laravel 13 compatibility in the package documentation, specifically mentioning this configuration requirement for users who have caching enabled.
Environment
- Laravel: 13.x
- PHP: 8.3+
- hisorange/browser-detect: 5.0.3
When using this package with Laravel 13, the
parse()method inhisorange\BrowserDetect\Parsercan return__PHP_Incomplete_Classinstead of aResultInterfaceobject when the result is retrieved from cache. This causes a fatal type error.Steps to Reproduce
The following code demonstrates the issue by parsing a user agent string twice (first call creates cache, second call retrieves from cache):
Expected Output
Actual Output
Root Cause
Laravel 13 introduced a security feature that requires a whitelist of classes that can be unserialized from cache. This prevents arbitrary class deserialization vulnerabilities. See the Laravel 13 upgrade guide for details.
When
hisorange\BrowserDetect\Resultis not in the whitelist, Laravel's cache system cannot reconstruct the object during unserialization, resulting in__PHP_Incomplete_Class.Solution
Add the
Resultclass to theserializable_classesarray in yourconfig/cache.phpfile:Alternatively, if you trust all cached data, you can use:
Note: After updating the configuration, clear your cache:
Documentation Suggestion
It would be helpful to add a note about Laravel 13 compatibility in the package documentation, specifically mentioning this configuration requirement for users who have caching enabled.
Environment