什么是确定 PHP 脚本命令行与 HTTP 执行的规范方式?

169

我有一个PHP脚本,需要确定它是通过命令行还是HTTP执行的,主要是为了输出格式的目的。有没有一种标准的方法来做到这一点?我原以为可以检查SERVER['argc'],但实际上即使使用'Apache 2.0 Handler'服务器API时也会填充该变量。

5个回答

247

使用php_sapi_name()函数。

if (php_sapi_name() == "cli") {
    // In cli-mode
} else {
    // Not in cli-mode
}

以下是文档中的一些相关注释:

php_sapi_name — 返回 Web 服务器和 PHP 之间的接口类型

虽然不是详尽无遗,但可能的返回值包括 aolserver、apache、apache2filter、apache2handler、caudium、cgi(直到 PHP 5.3)、cgi-fcgi、cli、cli-server、continuity、embed、isapi、litespeed、milter、nsapi、phttpd、pi3web、roxen、thttpd、tux 和 webjames。

在 PHP >= 4.2.0 中,还有一个预定义常量 PHP_SAPI,它具有与 php_sapi_name() 相同的值。


谢谢。我很好奇为什么文档示例检查前3个字符,而描述说明字符串应该完全是“cgi”,但除此之外,我认为这是完美的。 - Bobby Jack
除非返回的字符串是“cgi”,这也表明php是从控制台执行的。就像我的情况一样,你也知道。 - Adriano Varoli Piazza
@Adriano:也许在你的情况下,php-cgi 用于执行脚本。 - user3850
3
@Bobby,php.net文档中的示例实际上通过查看字符串的前三个字符来匹配“cgi”和“cgi-fcgi”......这就是为什么它实际上是有道理的。如果有什么不对,那只是为了让@hop知道,他称php不是专业程序员的语言:D - ChrisR
1
一个有趣的笔记是:http://php.net/manual/en/function.php-sapi-name.php,根据实际调用的二进制文件,你可以从命令行运行PHP,仍然获得CGI-FGI。 - DAB
显示剩余2条评论

23

这将始终有效。(如果PHP版本为4.2.0或更高)

define('CLI', PHP_SAPI === 'cli');

这使得在你的脚本顶部使用它非常容易:

<?php PHP_SAPI === 'cli' or die('not allowed');

9
你的第二段代码似乎是一个不合逻辑的推论,我会期望看到 CLI or die('not allowed'); - Madbreaks
1
@Madbreaks,我在说明两种不同的用法。我假设是要么使用其中一种,要么使用另一种 - 但如果你两个都用的话,那么 CLI or die('not allowed'); 是完美的。 - Xeoncross
10
“Which makes it easy to use at the top of your scripts”这句话并没有让它听起来像是两种不同的用法。是的,我是一个死灵法师。 - George Dimitriadis

11

以下是Drupal 7的实现:drupal_is_cli()

function drupal_is_cli() {
  return (!isset($_SERVER['SERVER_SOFTWARE']) && (php_sapi_name() == 'cli' || (is_numeric($_SERVER['argc']) && $_SERVER['argc'] > 0)));
}

然而,Drupal 8 建议使用 PHP_SAPI === 'cli'


10

我认为

$_SERVER['REMOTE_ADDR']

从CLI中不会填充此项。

同时,$_SERVER超全局变量中所有HTTP_*键在CLI中也不会被填充,或者按照hop所提到的正确方法执行 :-)


5
php_sapi_name文档页面清楚地说明了它的工作原理:

返回一个描述PHP正在使用的接口类型(服务器API,SAPI)的小写字符串....

虽然不是详尽无遗,但可能的返回值包括aolserver、apache、apache2filter、apache2handler、caudium、cgi(直到PHP 5.3)、cgi-fcgi、cli、continuity、embed、isapi、litespeed、milter、nsapi、phttpd、pi3web、roxen、thttpd、tux和webjames。

我不确定为什么hop认为PHP不适合严肃的程序员(我是一名严肃的程序员,我每天都在使用PHP),但如果他想要帮助澄清文档,那么也许他可以审查PHP可以运行的所有可能的Web服务器,并确定每个服务器的所有可能接口类型的名称。只需确保随着新的Web服务器和接口的添加而更新该列表。

Bobby也说:

我很好奇为什么文档示例检查前3个字符,而描述则说明字符串应完全是“CGI”

示例的描述如下:

此示例检查子字符串cgi,因为它也可能是cgi-fcgi。


啊 - 要么那天我非常不注意,要么这个例子已经更新了,自从我发表评论以来。不过,我完全同意你关于 PHP 的观点;抨击变得非常令人疲倦。 - Bobby Jack

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接