Jaki jest kanoniczny sposób określania wykonania skryptu PHP w wierszu poleceń w porównaniu z wykonaniem http?

155

Mam skrypt PHP, który musi określić, czy został wykonany za pomocą wiersza poleceń, czy przez HTTP, głównie w celu formatowania danych wyjściowych. Jaki jest kanoniczny sposób na zrobienie tego? Myślałem, że to inspekcja SERVER['argc'], ale okazuje się, że jest to zapełnione, nawet podczas korzystania z interfejsu API serwera „Apache 2.0 Handler”.

Bobby Jack
źródło

Odpowiedzi:

228

Użyj php_sapi_name()funkcji.

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

Oto kilka istotnych uwag z dokumentacji:

php_sapi_name - Zwraca typ interfejsu między serwerem WWW a PHP

Chociaż nie jest to wyczerpujące, możliwe wartości zwracane obejmują aolserver, apache, apache2filter, apache2handler, caudium, cgi (do PHP 5.3), cgi-fcgi, cli, cli-server, continuity, embed, isapi, litespeed, milter, nsapi, phttpd, pi3web, roxen, thttpd, tux i webjames.

W PHP> = 4.2.0 istnieje również predefiniowana stała PHP_SAPI, która ma taką samą wartość jak php_sapi_name().

Andy Fleming
źródło
Dzięki. Jestem zaintrygowany, dlaczego doktor. przykład sprawdza pierwsze 3 znaki, podczas gdy opis stwierdza, że ​​ciąg powinien być dokładnie „cgi”, ale poza tym uważam, że jest to idealne.
Bobby Jack,
chyba że, oczywiście, zwrócony ciąg to „cgi”, co również wskazuje na wykonanie php z konsoli. Tak jak w moim przypadku.
Adriano Varoli Piazza
@Adriano: być może w twoim przypadku php-cgi jest używane do wykonania skryptu.
3
@Bobby, przykład w dokumentacji php.net pasuje zarówno do „cgi”, jak i do „cgi-fcgi”, po prostu patrząc na pierwsze trzy znaki ciągu… dlatego i to ma sens. Jeśli już, to po prostu odzyskać @hop za wywołanie php bez języka dla poważnych programistów: D
ChrisR
1
interesująca uwaga: php.net/manual/en/function.php-sapi-name.php jest taka, że ​​w zależności od rzeczywistego wywoływanego pliku binarnego, możesz uruchomić php z wiersza poleceń i nadal uzyskać cgi-fgi
DAB
22

To zawsze zadziała. (Jeśli wersja PHP to 4.2.0 lub nowsza)

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

Co sprawia, że ​​jest łatwy w użyciu u góry skryptów:

<?php PHP_SAPI === 'cli' or die('not allowed');
Xeoncross
źródło
8
Twój drugi fragment wydaje się nie być sekwencją, spodziewałbym sięCLI or die('not allowed');
Madbreaks
1
@Madbreaks, podałem dwa różne zastosowania. Ja zakładając, albo jeden albo drugi - ale jeśli używasz zarówno wtedy CLI or die('not allowed');jest doskonały.
Xeoncross
Dzięki za wyjaśnienie, +1
Madbreaks
7
Which makes it easy to use at the top of your scriptsnie sprawia, że ​​brzmi to jak dwa oddzielne zastosowania. Tak, jestem nekromantą.
George Dimitriadis
9

Oto implementacja 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)));
}

Jednak Drupal 8 zaleca używaniePHP_SAPI === 'cli'

ya.teck
źródło
8

Myślę

$_SERVER['REMOTE_ADDR']

nie zostanie wypełniony z CLI.

Ponadto wszystkie klucze HTTP_ * w superglobalnej $ _SERVER nie zostaną wypełnione z CLI, lub zrobią to we właściwy sposób, o którym właśnie wspomniano :-)

Vinko Vrsalovic
źródło
4

Strona dokumentacji dla php_sapi_name jasno określa, jak to działa:

Zwraca mały ciąg znaków opisujący typ interfejsu (API serwera, SAPI), z którego korzysta PHP ....

Chociaż nie jest to wyczerpujące, możliwe wartości zwracane obejmują aolserver, apache, apache2filter, apache2handler, caudium, cgi (do PHP 5.3), cgi-fcgi, cli, continuity, embed, isapi, litespeed, milter, nsapi, phttpd, pi3web, roxen, thttpd, tux i webjames.

Nie jestem pewien, dlaczego Hop nie uważa, że ​​PHP jest dla poważnych programistów (jestem poważnym programistą i używam PHP na co dzień), ale jeśli chce pomóc w wyjaśnieniu dokumentacji, być może może przeprowadzić audyt wszystkich możliwych serwerów internetowych na którym PHP może działać i określa nazwy wszystkich możliwych typów interfejsów dla każdego serwera. Po prostu pamiętaj, aby aktualizować tę listę w miarę dodawania nowych serwerów internetowych i interfejsów.

Ponadto Bobby powiedział:

Jestem zaintrygowany, dlaczego doktor. przykład sprawdza pierwsze 3 znaki, podczas gdy opis stwierdza, że ​​ciąg powinien być dokładnie „CGI”

Opis przykładu stwierdza:

Ten przykład sprawdza podciąg cgi, ponieważ może to być również cgi-fcgi.

Steve
źródło
Ach - albo byłem tego dnia niesamowicie nieuważny, albo przykład został zaktualizowany, odkąd opublikowałem ten komentarz. Całkowicie zgadzam się jednak z Twoimi uwagami na temat PHP; walenie staje się BARDZO męczące.
Bobby Jack