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

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

この本文には実行可能なタグ等が含まれるため、安全のためHTMLソースとして表示しています。本文データは変更していません。

<table border="1" cellpadding="6" cellspacing="0" style="border-collapse:collapse;background:#fffbea;border:1px solid #f4c430;margin:1em 0;width:100%"><tr><td style="background:#f4c430;color:#000;font-weight:bold;padding:8px">この記事の要点</td></tr><tr><td style="padding:10px"><ul><li>PHP: <code>PHP_OS_FAMILY</code> (PHP 7.2+) が最も簡単。値は <strong>Windows / Linux / Darwin / BSD / Solaris / Unknown</strong></li><li>古い PHP: <code>PHP_OS</code> / <code>php_uname("s")</code> / <code>DIRECTORY_SEPARATOR</code> の比較</li><li>Laravel: 環境名は <code>app()->environment()</code> または <code>App::environment("local")</code>。<code>.env</code> の <code>APP_ENV</code> 値</li><li>JavaScript (ブラウザ): <code>navigator.userAgent</code> / <code>navigator.platform</code> / <code>navigator.userAgentData</code> (Client Hints)</li><li>Node.js: <code>process.platform</code> (win32 / linux / darwin) + <code>process.arch</code> (x64 / arm64)</li><li><strong>環境変数で分岐</strong>するほうが安全(<code>APP_ENV=production</code> 等)。OS 判定は最終手段</li><li>CI 判定: GitHub Actions <code>$GITHUB_ACTIONS</code>、GitLab <code>$GITLAB_CI</code>、一般 <code>$CI=true</code></li></ul></td></tr></table>
<h2>OS / 環境判定が必要になるケース</h2>

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

<h2>PHP での環境判定</h2>
<pre style="background:#1e293b;color:#e2e8f0;padding:1em;border-radius:6px;overflow-x:auto;line-height:1.5"><code class="language-php"><?php

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

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

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

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

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

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

// === 環境変数で分岐(最も安全) ===
$env = getenv(&apos;APP_ENV&apos;) ?: &apos;production&apos;;
if ($env === &apos;local&apos; || $env === &apos;development&apos;) {
    error_reporting(E_ALL);
    ini_set(&apos;display_errors&apos;, &apos;1&apos;);
}</code></pre>
<h2>Laravel の環境判定</h2>
<pre style="background:#1e293b;color:#e2e8f0;padding:1em;border-radius:6px;overflow-x:auto;line-height:1.5"><code class="language-php"><?php

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

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

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

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

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

// @production
//     <!-- Google Analytics タグ -->
// @endproduction</code></pre>
<h2>JavaScript (ブラウザ) での環境判定</h2>
<pre style="background:#1e293b;color:#e2e8f0;padding:1em;border-radius:6px;overflow-x:auto;line-height:1.5"><code class="language-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 = &apos;ontouchstart&apos; in window || navigator.maxTouchPoints > 0;

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

// === 画面サイズ / ブレークポイント ===
const isMobile = window.matchMedia(&apos;(max-width: 768px)&apos;).matches;</code></pre>
<h2>Node.js での環境判定</h2>
<pre style="background:#1e293b;color:#e2e8f0;padding:1em;border-radius:6px;overflow-x:auto;line-height:1.5"><code class="language-javascript">// === プラットフォーム ===
console.log(process.platform);
// "win32" / "linux" / "darwin" / "freebsd" / "openbsd" / "sunos" / "aix"

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

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

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

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

// === CI 判定 ===
if (process.env.CI === &apos;true&apos;) {
  console.log(&apos;Running in CI&apos;);
}
if (process.env.GITHUB_ACTIONS) { /* GitHub Actions */ }
if (process.env.GITLAB_CI)      { /* GitLab CI */ }
if (process.env.CIRCLECI)       { /* CircleCI */ }</code></pre>
<h2>主要 CI の検知用環境変数</h2>

<table border="1" cellpadding="6" cellspacing="0" style="border-collapse:collapse;width:100%">
<thead><tr style="background:#e3f2fd"><th>CI / プラットフォーム</th><th>判定用環境変数</th></tr></thead>
<tbody>
<tr><td>汎用</td><td><code>CI=true</code></td></tr>
<tr><td>GitHub Actions</td><td><code>GITHUB_ACTIONS=true</code> / <code>GITHUB_RUN_ID</code></td></tr>
<tr><td>GitLab CI</td><td><code>GITLAB_CI=true</code> / <code>CI_JOB_ID</code></td></tr>
<tr><td>CircleCI</td><td><code>CIRCLECI=true</code></td></tr>
<tr><td>Jenkins</td><td><code>JENKINS_URL</code> / <code>BUILD_NUMBER</code></td></tr>
<tr><td>Travis CI</td><td><code>TRAVIS=true</code></td></tr>
<tr><td>Azure Pipelines</td><td><code>TF_BUILD=True</code></td></tr>
</tbody>
</table>

<h2>ベストプラクティス</h2>

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

<h2>FAQ</h2>

<p><strong>Q: PHP_OS_FAMILY と PHP_OS の違い</strong><br />
A: <code>PHP_OS_FAMILY</code> は <code>Windows / Linux / Darwin / BSD / Solaris / Unknown</code> の <strong>カテゴリ</strong>。<code>PHP_OS</code> は <code>WINNT / Linux / Darwin</code> 等の詳細。分岐目的では <code>PHP_OS_FAMILY</code> が便利。</p>

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

<p><strong>Q: CI でだけテストをスキップしたい</strong><br />
A: <code>process.env.CI</code> や <code>getenv("CI")</code> でガード。PHPUnit なら <code>@group ci-skip</code> + <code>--exclude-group ci-skip</code>。</p>