tivie/php-os-detector
tivie/php-os-detector is a small PHP library for identifying the operating system your code is running on. It detects OS family, name, and version across platforms, helping you branch logic, adjust paths, or handle environment-specific behavior reliably.
Install (Composer):
composer require tivie/php-os-detector
There are no Laravel service providers, config files, or migrations to publish — this is a plain PHP utility class. That’s a feature, not a bug.
Where to look first:
Open vendor/tivie/php-os-detector/src/OSDetector.php. The whole library is essentially one class with a set of static boolean methods such as isWindows(), isLinux(), isOSX(), and isUnix(). Once you’ve read that file, you know the package. There is nothing hidden behind a facade or a boot sequence.
First use case: The most common day-one use in a Laravel app is deciding how to branch OS-specific shell commands — for example, spawning a subprocess in a queued job or a console command:
use Tivie\OS;
if (OS::isWindows()) {
$cmd = 'dir /B';
} elseif (OS::isUnix()) {
$cmd = 'ls -1';
}
Process::run($cmd);
You can use it inline (no container binding needed):
if (\Tivie\OS::isLinux()) {
// Linux-only path, e.g. use `apt-get` wrapper
}
Because the class is static and dependency-free, you can call it from anywhere — controllers, jobs, Artisan commands, package code — without touching config/app.php.
Wrap Symfony\Component\Process (already shipped with Laravel) so you don’t hard-code C:\ vs /usr/bin:
$binary = OS::isWindows() ? 'php.exe' : 'php';
$process = new Process([$binary, 'artisan', 'schedule:run']);
$process->run();
Use it in a config file to set sensible defaults for paths that differ across OSes:
// config/services.php
return [
'imagemagick' => [
'binary' => env('IMAGEMAGICK_BIN', OS::isWindows()
? 'C:\\Program Files\\ImageMagick\\magick.exe'
: '/usr/local/bin/magick'),
],
];
This lets ops override via .env while keeping sane dev-machine defaults.
In phpunit.xml or a base TestCase, skip tests that can’t run on the local OS:
protected function setUp(): void
{
parent::setUp();
if (OS::isWindows()) {
$this->markTestSkipped('POSIX-only test');
}
}
For testability, wrap the static calls behind an injectable interface rather than calling OS:: directly in application code:
interface OsInfo { public function isWindows(): bool; }
class TivieOsInfo implements OsInfo {
public function isWindows(): bool { return OS::isWindows(); }
}
// AppServiceProvider
$this->app->bind(OsInfo::class, TivieOsInfo::class);
Now your jobs can be unit-tested without needing a Windows runtime.
Typical Laravel console commands that do OS-specific setup (symlinks, file permissions, clearing caches) become:
public function handle()
{
if (OS::isWindows()) {
$this->warn('Symlink creation requires Administrator on Windows.');
} else {
$this->call('storage:link');
}
}
Exposing OS to the UI is rarely correct, but it’s useful for admin dashboards:
@if(\Tivie\OS::isLinux())
<span class="badge">Linux host</span>
@endif
Prefer passing it via a View Composer or View::share('os', ...) rather than calling static methods directly in templates.
Static-only API — no DI container. The class has no constructor injection, so testing code that calls OS::isWindows() directly requires mocking the OS or using a wrapper (Pattern 4). Plan for a thin adapter if you test OS-specific logic.
PHP_OS vs PHP_OS_FAMILY. The package was last released in 2017 — before PHP_OS_FAMILY (added PHP 7.2) and before PHP 8. It relies on PHP_OS and a few constants. On modern PHP 8.x it still works, but you may get deprecation notices on very new runtimes. Consider pinning ^1.2 and checking composer why-not if you see oddities.
Not a replacement for PHP_OS_FAMILY on modern PHP. If you only need Windows vs Unix, PHP_OS_FAMILY ('Windows', 'Linux', 'Darwin', 'BSD') is a cleaner built-in. Reach for tivie/php-os-detector when you need its slightly richer helpers or are supporting PHP < 7.2 across a shared codebase.
Container/Docker pitfalls. Inside an Alpine container, OS::isLinux() returns true even if the host is macOS. That’s the correct answer (it detects the runtime OS, not the developer’s laptop), but it surprises people debugging “Why does this branch differently in CI?” Always remember you’re inspecting the PHP process’s OS, not the host machine.
WSL is Linux. Windows Subsystem for Linux reports as Linux — if you have branches keyed on “real Windows behavior” for path separators, they won’t trigger under WSL. Use DIRECTORY_SEPARATOR or PHP_OS_FAMILY if you actually care about path semantics.
No config to publish — don’t look for one. There’s no config/os-detector.php, no facade, no provider auto-discovery. If a tutorial suggests php artisan vendor:publish, it’s wrong for this package.
Extension points are essentially nonexistent. There’s no driver system, no strategy interface. If you need richer OS info (distro name, kernel version), look at symfony/process + php_uname('-a') or a dedicated package like symfony/polyfill-php80's family constants. Don’t try to subclass OSDetector — the methods are static.
Composer license note. Apache-2.0 is fine for app use, but if you redistribute, retain the LICENSE file; the package does not ship with an MIT exception.
Debugging tip. If a branch behaves unexpectedly, dump the raw truth first:
dump(PHP_OS, PHP_OS_FAMILY ?? null, php_uname());
Then compare to what OS::is*() returns on that machine. It usually resolves in one line.
Consider it “vendored utility” status. With a 2017 last release and only ~20 stars, treat this as a stable but unmaintained leaf dependency. If you need active upkeep, wrapping PHP_OS_FAMILY in your own tiny helper is often a better long-term bet — but for existing apps and legacy PHP support, tivie/php-os-detector is small, safe, and does exactly one thing.
How can I help you explore Laravel packages today?