この内容は古いバージョンです。最新バージョンを表示するには、戻るボタンを押してください。
バージョン:4
ページ更新者:guest
更新日時:2026-06-11 07:10:02

タイトル: 動作環境による分岐処理
SEOタイトル: PHP / JavaScript / Node.js で OS・実行環境を判定して処理分岐する方法

この記事の要点
  • PHP: PHP_OS_FAMILY (PHP 7.2+) が最も簡単。値は Windows / Linux / Darwin / BSD / Solaris / Unknown
  • 古い PHP: PHP_OS / php_uname("s") / DIRECTORY_SEPARATOR の比較
  • Laravel: 環境名は app()->environment() または App::environment("local").envAPP_ENV
  • JavaScript (ブラウザ): navigator.userAgent / navigator.platform / navigator.userAgentData (Client Hints)
  • Node.js: process.platform (win32 / linux / darwin) + process.arch (x64 / arm64)
  • 環境変数で分岐するほうが安全(APP_ENV=production 等)。OS 判定は最終手段
  • CI 判定: GitHub Actions $GITHUB_ACTIONS、GitLab $GITLAB_CI、一般 $CI=true

OS / 環境判定が必要になるケース

  • パス区切り(Windows \ vs Unix /)の調整
  • 外部コマンド呼び出し(where vs whichcmd /c vs sh -c
  • 改行コード(CRLF / LF)の正規化
  • 開発環境とプロダクションで挙動を分ける(ログ詳細度、メール送信先など)
  • CI でだけスキップしたいテスト

PHP での環境判定

<?php

// === OS 判定(PHP 7.2+ 推奨) ===
echo PHP_OS_FAMILY;   // "Windows" / "Linux" / "Darwin" / "BSD" / "Solaris" / "Unknown"

if (PHP_OS_FAMILY === 'Windows') {
    $cmd = 'where php';
} else {
    $cmd = 'which php';
}

// === 古い PHP / 詳細情報 ===
echo PHP_OS;                // "WINNT" / "Linux" / "Darwin"
echo php_uname('s');        // OS 名
echo php_uname('r');        // カーネルバージョン
echo php_uname('m');        // x86_64 / arm64 等
echo DIRECTORY_SEPARATOR;   // "\" or "/"
echo PATH_SEPARATOR;        // ";" or ":"

// === SAPI(実行形態) ===
echo PHP_SAPI;              // "cli" / "apache2handler" / "fpm-fcgi" / "cli-server"

if (PHP_SAPI === 'cli') {
    // CLI からの呼び出しのみ実行
}

// === PHP バージョン分岐 ===
if (PHP_VERSION_ID >= 80100) {
    // PHP 8.1 以上の機能を使う
}

// === 環境変数で分岐(最も安全) ===
$env = getenv('APP_ENV') ?: 'production';
if ($env === 'local' || $env === 'development') {
    error_reporting(E_ALL);
    ini_set('display_errors', '1');
}

Laravel の環境判定

<?php

// .env の APP_ENV=local / staging / production を判定

// 単純比較
if (app()->environment('local')) {
    // ローカルだけのデバッグ処理
}

// 複数チェック
if (app()->environment(['local', 'staging'])) {
    // 開発系全般
}

// 本番のみ
if (app()->environment('production')) {
    Mail::to($realUser)->send(new WelcomeMail());
} else {
    // 開発中はテスト用宛先へ
    Mail::to('dev@example.com')->send(new WelcomeMail());
}

// Blade 内
// @env('local')
//     <script src="/dev-only.js"></script>
// @endenv

// @production
//     <!-- Google Analytics タグ -->
// @endproduction

JavaScript (ブラウザ) での環境判定

// === User-Agent ベース(非推奨だが古典的) ===
const ua = navigator.userAgent;

const isIOS     = /iPad|iPhone|iPod/.test(ua);
const isAndroid = /Android/.test(ua);
const isMac     = /Macintosh|Mac OS/.test(ua);
const isWin     = /Windows/.test(ua);

// === navigator.platform(非推奨だが現役) ===
console.log(navigator.platform);
// "Win32" / "MacIntel" / "Linux x86_64" / "iPhone" / "iPad"

// === User-Agent Client Hints(Chromium 系の新 API) ===
if (navigator.userAgentData) {
  console.log(navigator.userAgentData.platform);  // "Windows" / "macOS" / "Android"
  console.log(navigator.userAgentData.mobile);    // true / false
  console.log(navigator.userAgentData.brands);
  // [{brand:"Chromium",version:"120"}, ...]
}

// === タッチデバイス判定 ===
const isTouch = 'ontouchstart' in window || navigator.maxTouchPoints > 0;

// === ダークモード判定 ===
const isDark = window.matchMedia('(prefers-color-scheme: dark)').matches;

// === 画面サイズ / ブレークポイント ===
const isMobile = window.matchMedia('(max-width: 768px)').matches;

Node.js での環境判定

// === プラットフォーム ===
console.log(process.platform);
// "win32" / "linux" / "darwin" / "freebsd" / "openbsd" / "sunos" / "aix"

console.log(process.arch);
// "x64" / "arm64" / "ia32"

// 分岐例
const isWindows = process.platform === 'win32';
const cmd = isWindows ? 'npm.cmd' : 'npm';

// === Node.js バージョン ===
console.log(process.versions.node);  // "20.10.0"
const [major] = process.versions.node.split('.').map(Number);
if (major < 18) {
  throw new Error('Node.js 18+ required');
}

// === 環境変数(最重要) ===
const env = process.env.NODE_ENV || 'development';
if (env === 'production') {
  // 本番のみ
}

// === CI 判定 ===
if (process.env.CI === 'true') {
  console.log('Running in CI');
}
if (process.env.GITHUB_ACTIONS) { /* GitHub Actions */ }
if (process.env.GITLAB_CI)      { /* GitLab CI */ }
if (process.env.CIRCLECI)       { /* CircleCI */ }

主要 CI の検知用環境変数

CI / プラットフォーム判定用環境変数
汎用CI=true
GitHub ActionsGITHUB_ACTIONS=true / GITHUB_RUN_ID
GitLab CIGITLAB_CI=true / CI_JOB_ID
CircleCICIRCLECI=true
JenkinsJENKINS_URL / BUILD_NUMBER
Travis CITRAVIS=true
Azure PipelinesTF_BUILD=True

ベストプラクティス

  • OS 判定よりも環境変数で分岐するほうが移植性が高い
  • UA Sniffing は壊れやすい → Feature Detection(その API が存在するかを直接調べる)を優先
  • PHP/Node 共に .envgit にコミットしない.env.example を雛形に
  • テスト用にモック可能な層に抽象化(Platform::isWindows() のようなラッパー関数)

FAQ

Q: PHP_OS_FAMILY と PHP_OS の違い
A: PHP_OS_FAMILYWindows / Linux / Darwin / BSD / Solaris / UnknownカテゴリPHP_OSWINNT / Linux / Darwin 等の詳細。分岐目的では PHP_OS_FAMILY が便利。

Q: navigator.userAgent は信頼できる?
A: 偽装可能で、ブラウザ更新でフォーマットが変わるため信頼度は低い。代替として Client Hints (navigator.userAgentData) と Feature Detection を組み合わせるのが現代的です。

Q: CI でだけテストをスキップしたい
A: process.env.CIgetenv("CI") でガード。PHPUnit なら @group ci-skip + --exclude-group ci-skip