PHP 可運行於多種 SAPI (Server API) 環境,透過 php_sapi_name() 識別當前環境,可實現 CLI/Web/嵌入式等差異化邏輯。
核心函式
<?php
$sapi = php_sapi_name();
echo "當前 SAPI: $sapi";
常見 SAPI 返回值對照
| 環境 | php_sapi_name() 返回值 | 備註 |
| Apache 模組 (mod_php) | apache2handler | 最常見生產環境 |
| Apache CGI / FastCGI | cgi-fcgi | PHP-FPM、suPHP |
| Nginx + PHP-FPM | fpm-fcgi | 現代主流部署 |
| 命令列 (CLI) | cli | 腳本、定時任務、Queue Worker |
| 內建 Web Server | cli-server | php -S localhost:8000 |
| IIS (ISAPI) | isapi | Windows IIS 6 |
| IIS (FastCGI) | cgi-fcgi | Windows IIS 7+ |
| 嵌入式 (Embed) | embed | PHP 嵌入 C/C++ 應用 |
| phpdbg 除錯器 | phpdbg | PHP 5.6+ 內建除錯器 |
實務應用場景
1. CLI 專用邏輯 (定時任務、佇列處理)
<?php
if (php_sapi_name() === 'cli') {
// CLI 環境:無限執行時間、無輸出緩衝、可讀取 stdin
set_time_limit(0);
ini_set('memory_limit', '512M');
// 讀取管道輸入
$stdin = fopen('php://stdin', 'r');
while (($line = fgets($stdin)) !== false) {
processLine(trim($line));
}
// 彩色輸出
echo "\033[32m成功\033[0m\n";
exit(0);
}
// Web 環境:正常 HTTP 處理
handleHttpRequest();
2. 區分 Apache/Nginx 針對性優化
<?php
$sapi = php_sapi_name();
if (strpos($sapi, 'apache') !== false) {
// Apache mod_php: 進程模型、.htaccess 生效
apache_setenv('no-gzip', 1); // 關閉 mod_deflate 避免雙重壓縮
} elseif ($sapi === 'fpm-fcgi') {
// PHP-FPM: fastcgi_finish_request() 可用
// 適合異步任務、大檔案下載後續處理
}
3. 統一入口自動適配
<?php
// public/index.php
require __DIR__ . '/../vendor/autoload.php';
$sapi = php_sapi_name();
if ($sapi === 'cli') {
// Artisan/Console 入口
$app = require __DIR__ . '/../bootstrap/console.php';
$kernel = $app->make(Illuminate\Contracts\Console\Kernel::class);
$status = $kernel->handle(
$input = new Symfony\Component\Console\Input\ArgvInput,
new Symfony\Component\Console\Output\ConsoleOutput
);
exit($status);
} elseif ($sapi === 'cli-server') {
// 開發測試用內建伺服器:靜態檔案直接服務
$uri = urldecode(parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH));
if ($uri !== '/' && file_exists(__DIR__ . $uri)) {
return false; // 讓內建伺服器直接服務靜態檔
}
}
// 正常 HTTP 請求處理
$app = require __DIR__ . '/../bootstrap/app.php';
$kernel = $app->make(Illuminate\Contracts\Http\Kernel::class);
$response = $kernel->handle(
$request = Illuminate\Http\Request::capture()
);
$response->send();
$kernel->terminate($request, $response);
4. 環境感知配置載入
<?php
function loadConfig() {
$sapi = php_sapi_name();
$base = __DIR__ . '/config';
// 共用配置
$config = require "$base/app.php";
// 環境專屬覆蓋
$envConfigs = [
'cli' => 'console.php',
'cli-server' => 'local.php',
'fpm-fcgi' => 'production.php',
'apache2handler' => 'production.php',
];
if (isset($envConfigs[$sapi])) {
$override = require "$base/{$envConfigs[$sapi]}";
$config = array_merge_recursive($config, $override);
}
// .env 覆蓋 (最高優先級)
if (file_exists(__DIR__ . '/.env')) {
$dotenv = new Symfony\Component\Dotenv\Dotenv();
$dotenv->load(__DIR__ . '/.env');
}
return $config;
}
相關超全域變數輔助判斷
| 變數 | CLI 環境 | Web 環境 |
| $_SERVER['argc'] | >= 1 | 未設定 |
| $_SERVER['argv'] | 參數陣列 | 未設定 |
| $_SERVER['REQUEST_METHOD'] | 未設定 | GET/POST... |
| $_SERVER['HTTP_HOST'] | 未設定 | 域名 |
| STDIN/STDOUT/STDERR | 可用 | 不可用 |
常數判斷替代方案 (PHP 7.2+)
<?php
// 定義於 php.h,編譯時確定
echo PHP_SAPI; // 等同 php_sapi_name(),但略快 (無函式呼叫)
// 預定義常數
defined('STDIN') // CLI 專用
defined('STDOUT') // CLI 專用
defined('STDERR') // CLI 專用