PHP-現在の呼び出しがCLIまたはWebサーバーのどちらからであるかを最もよく判断するにはどうすればよいですか?


回答:


308

php_sapi_nameインターフェイスタイプの小文字の文字列を返すため、使用する関数です。さらに、PHP定数がありPHP_SAPIます。

ドキュメントはここにあります:http : //php.net/php_sapi_name

たとえば、PHPがCLIから実行されているかどうかを確認するには、次の関数を使用できます。

function isCommandLineInterface()
{
    return (php_sapi_name() === 'cli');
}

11
より簡単な例:return php_sapi_name() == 'cli';
サベージマン、2010

11
私は調査を行いましたphp-cgi。これを使用してスクリプトを呼び出しても機能しません。次に、cgi-fcgi文字列を返します。ブラウザからスクリプトをWebページとしてロードすると、が表示されますapache2handler。お役に立てれば。変数php-cgiを導入するために使用する必要がありました$_GETphp-cgi myscript.php arg1=one arg2=two。と等しくないapache2handlerかどうかのテストは、で問題ありませんapache
セバスチャン

3
この方法についての小さな警告:cronジョブから実行した場合戻りません"cli"$_SERVERリクエストがHTTP経由かどうかをより確実に判断するために、内部から選択するさまざまなキーがあります。
omn​​inonsense

2
@omninonsense PHP 7.2.7でテストすると、cliが返されます。
Jose Nobile

38

私はこの機能を数年間使用しています

function is_cli()
{
    if ( defined('STDIN') )
    {
        return true;
    }

    if ( php_sapi_name() === 'cli' )
    {
        return true;
    }

    if ( array_key_exists('SHELL', $_ENV) ) {
        return true;
    }

    if ( empty($_SERVER['REMOTE_ADDR']) and !isset($_SERVER['HTTP_USER_AGENT']) and count($_SERVER['argv']) > 0) 
    {
        return true;
    } 

    if ( !array_key_exists('REQUEST_METHOD', $_SERVER) )
    {
        return true;
    }

    return false;
}

10
array_key_exists('REQUEST_METHOD', $_SERVER) return true;WAT?
biziclop 2016年

@biziclop、チェックはリクエストのソースのarray_key_exists('REQUEST_METHOD', $_SERVER)検出を支援するために正しいです。すると、CLI、スーパーグローバル配列がWILL NOTキーを持っている、それだけで、要求をWeb経由で行われたとき、それをチェックするときに、それゆえ、作者がターゲットに絶対に存在します。$_SERVERREQUEST_METHOD
Julio Marchi

1
@JulioMarchi:それはいけませんreturn false;かんif ( ! array_key_exists(…)) return true;
biziclop 2016

2
@biziclop、あなたは完全に正しいです!!!! どのように私はそのような巨大な細部を見逃すことができましたか??? 私の恥... :)。確かに、KEY 'REQUEST_METHOD'が見つからない場合、関数FALSEは「CLI」を示すように戻るはずです。関数自体のスコープに注意を払わなかったことに対する私の謝罪...関数は実際に機能するので、著者はそれを修正する必要があります!
Julio Marchi 2016

私の場合、この関数はphp_sapi_name()ではなく機能しました。Webリクエストとcronjobの実行を区別する必要があり、php_sapi_name()の結果はどちらの場合も「php-cgi」でした。
luis.ap.uyen

36

php_sapi_name()これは実際にこのチェックを実行する最良の方法ではありません。これは、多くの可能な値に対するチェックに依存するためです。php-cgiバイナリは、コマンドライン、シェルスクリプト、またはcronジョブとして呼び出すことができ、(ほとんどの場合)これらも「cli」として扱う必要がありますが、php_sapi_name()ますが、これらに対して異なる値を返します(これは違います)プレーンバージョンのPHPの場合ですが、コードをどこでも機能させたいと思いませんか?)言うまでもなく、来年、PHPを使用する新しい方法が存在する可能性があります。私が気にしているのは、出力をHTMLでラップする必要があるかどうかである場合は、それについて考えたくありません。

幸い、PHPにはこれを具体的にチェックする方法があります。http_response_code()パラメータなしで使用するだけで、Webサーバータイプ環境から実行された場合はTRUEを返し、CLIタイプ環境から実行された場合はFALSEを返します。これがコードです:

$is_web=http_response_code()!==FALSE;

これを呼び出す前に、CLI(またはCLIのようなもの)から実行されているスクリプトから誤って(?)応答コードを設定した場合でも、これは機能します。


4
私が答えたとき、この質問はすでに古いものでした。この回答を賛成投票することは、説明がない場合を除いて、重複する別の回答を投稿するよりもおそらく便利でしょう。
krowe2 2017

「これを呼び出す前に、誤って(?)CLIから実行されているスクリプトからの応答コードを設定した場合でも機能します([...])」:(少なくとも)PHP 7.4.3以降、これは違います。http_response_code()CLIから実行するときにコードを設定するか、設定コードを返します。によって確認されました<?php function t() { echo var_export(http_response_code(), true) . ' -> ' . (http_response_code() !== false ? 'web' : 'cli') . "\n"; } t(); http_response_code(200); t(); http_response_code(false); t();。その場合http_response_code()===false、CLIを想定しても安全ですが、そうでない場合は他のメトリックも確認する必要があります。
セバスチャンB.

23

私は彼がPHP CLIが呼び出されているのか、それともWebリクエストからの応答なのかを意味していると思います。最善の方法はphp_sapi_name()、Webリクエストが実行されていた場合、それが実行されていた場合にApacheをエコーする方法を使用することです。

php_sapi_name()のphp ドキュメントから取られたいくつかのリスト:

  • aolserver
  • アパッチ
  • apache2filter
  • apache2handler
  • コーディウム
  • cgi(PHP 5.3まで)
  • cgi-fcgi
  • cli
  • cli-server(PHP 5.4以降の組み込みWebサーバー
  • 連続
  • 埋め込む
  • fpm-fcgi
  • isapi
  • ライトスピード
  • ミルター
  • nsapi
  • phttpd
  • pi3web
  • ロクセン
  • thttpd
  • タキシード
  • webjames

13

これはすべてのケースを処理するはずです(php-cgiを含む)

return (php_sapi_name() === 'cli' OR defined('STDIN'));

6
function is_cli() {
    return !http_response_code();
}

例:

if (is_cli()) {
    echo 'command line';
} else {
    echo 'browser';
}

2
マニュアルから、「response_codeが提供されておらず、Webサーバー環境(CLIアプリケーションなど)で呼び出されない場合、FALSEが返されます。response_codeが提供され、Webサーバーで呼び出されない場合、TRUEが返されます。環境(ただし、以前の応答ステータスが設定されていない場合のみ)」あなたは論理を逆に持っています。
krowe2 2017

1
+1。すごい。長年の実りのない研究の後...私は、PHPicsでノーベル記念賞を授与します。これは、実際に機能させるという彼の計り知れない貢献に対して@ krowe2と共有されました。おめでとう!
Sz。

何かが応答コードを設定した可能性があります... http_response_code(200);...ここで呼び出すhttp_response_code()と、200が返されます。
ブラッドケント

@BradKentこれは、Web環境からこれを呼び出した場合にのみ発生します。その場合、ステータスコードをゼロに設定しない限り(この方法は無効なHTTPステータスコードです)、このチェックは機能します。私のバージョンは、具体的にはFALSEをチェックするため、その場合でも機能します。http_response_code();CLI環境から呼び出された場合、実際のステータスコードに関係なく、常にFALSEを返します。これについてはすでに回答で説明しましたが、「戻り値」のマニュアルページを読んだり、試してみたりして、このことを知ることもできます。
krowe2

@ krowe2は php -r 'http_response_code(200); echo http_response_code()."\n";' "200"を出力します。ライブラリまたは無知のフレームワークが応答コードを設定していないことを保証できない場合http_response_code(cli環境でも)、これは機能します。個人的に、私は使用しています$isCli = \defined('STDIN') || isset($_SERVER['argv']) || \array_key_exists('REQUEST_METHOD', $_SERVER)
ブラッドケント

4

私はこれを使いました:

php_sapi_name() == 'cli' || (is_numeric($_SERVER['argc']) && $_SERVER['argc'] > 0)

これは、Drushのコードベース、environment.incによるもので、同様のチェックが行われます。


4
場合はregister_argc_argv設定され、その後、GET値の任意の量で渡すと発生しますargc0にならないために

3

試す

isset($_SERVER['REQUEST_METHOD'])

設定されている場合は、ブラウザを使用しています。

代わりに、あなたは

isset($_SERVER['argv'])

しかし、Windows CLI、IDKには当てはまらない場合があります。


1
「正しい」答えではありませんが、より信頼できるかもしれません
シャレット



0

$ _SERVER配列の一部のエントリが設定されているかどうかを確認することをお勧めします。

例えば:

if (isset($_SERVER['REQUEST_METHOD'])) {
        print "HTTP request\n";
} else {
        print "CLI invocation\n";
}

これは動作しませんphp-cgiコマンドラインは、それはそれを設定しますGETため:php-cgi -f file.php arg1=2
セバスチャン


0
// Detect CLI calls
define("IS_CLI_CALL",( strcmp(php_sapi_name(),'cli') == 0 ));

if(IS_CLI_CALL){
   //do you stuff here

}

0

簡単な方法は、$argv変数に問い合わせることです(とにかくコマンドラインパラメーターに対して行うでしょう)。パラメータがない場合でも$argv、空の配列を返します。

設定されている場合、cliが使用されました。次に、他のすべての呼び出しがWebサーバーなどを経由していると想定します。

例えば:

if (isset($argv)) {
  // Do the cli thing.
}

0

上記のシルバームーンの回答に基づいて、正しい改行を返すためにこの関数を使用しています。

/**
* Linebreak function
* @return "/n" if cli, else return <br>
*/
protected static function lb(){

    return (defined('STDIN') || php_sapi_name() === 'cli' || isset($_ENV['SHELL']) ||
    (empty($_SERVER['REMOTE_ADDR']) && !isset($_SERVER['HTTP_USER_AGENT']) && count($_SERVER['argv']) > 0) ||
    !isset($_SERVER['REQUEST_METHOD'])) ? "\n" : "<br>";

}

0

この質問に対する正しい答えは、その背後にある実際の意図によって異なります。

  • SAPIが決定要因ですか(Webコンテキストかどうか)。
  • または、情報は「ttyで実行されている」と解釈されますか?

前者の場合、与えられた回答と書かれたコメントは、有効な解決策を見つけるのに十分です。

後者の場合、ツールがcronjobとして実行されるか、別のデーモンからのバックグラウンドジョブとして実行されると、ここに記載されているレシピは失敗します。その場合STDIN、TTY かどうかをさらにテストすることをお勧めします。

function at_tty() {
    return defined("\STDIN") && posix_isatty(\STDIN);
}

-1

どのように、非常に多くの複雑なソリューション。どう...

if($_SERVER['REQUEST_SCHEME']=="http" or $_SERVER['REQUEST_SCHEME']=="https"){
    // must be browser :)
}

-17

私は試してみます:

echo exec('whoami');

通常、ウェブサーバーは別のユーザー名で実行されているので、それでわかります。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.