Apa cara kanonik untuk menentukan eksekusi commandline vs http dari skrip PHP?

155

Saya memiliki skrip PHP yang perlu ditentukan apakah sudah dieksekusi melalui command-line atau melalui HTTP, terutama untuk keperluan format-output. Apa cara kanonik melakukan ini? Saya pikir itu adalah untuk memeriksa SERVER['argc'], tetapi ternyata ini diisi, bahkan ketika menggunakan server API 'Apache 2.0 Handler'.

Bobby Jack
sumber

Jawaban:

228

Gunakan php_sapi_name()fungsinya.

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

Berikut adalah beberapa catatan yang relevan dari dokumen:

php_sapi_name - Mengembalikan jenis antarmuka antara server web dan PHP

Meskipun tidak lengkap, nilai-nilai pengembalian yang mungkin termasuk aolserver, apache, apache2filter, apache2handler, caudium, cgi (sampai PHP 5.3), cgi-fcgi, cli, cli-server, kontinuitas, embed, isapi, litespeed, milter, nsapi, phttpd, pi3web, roxen, thttpd, tux, dan webjames.

Dalam PHP> = 4.2.0, ada juga konstanta yang telah ditentukan sebelumnya PHP_SAPI,, yang memiliki nilai yang sama dengan php_sapi_name().

Andy Fleming
sumber
Terima kasih. Saya tertarik mengapa dok. contoh memeriksa 3 karakter pertama, sementara deskripsi menyatakan string harus persis "cgi" tetapi, selain itu, saya pikir ini sempurna.
Bobby Jack
kecuali, tentu saja, string yang dikembalikan adalah 'cgi', yang juga merupakan indikasi php dieksekusi dari konsol. Seperti, whaddayaknow, kasus saya.
Adriano Varoli Piazza
@Adriano: mungkin dalam kasus Anda php-cgi digunakan untuk menjalankan skrip.
3
@ Bob, contoh dalam dokumen php.net sebenarnya cocok dengan "cgi" dan "cgi-fcgi" dengan hanya melihat tiga karakter pertama dari string ... itu sebabnya dan itu benar-benar masuk akal. Jika ada itu hanya untuk mendapatkan kembali @hop untuk memanggil php tidak ada bahasa untuk programmer serius: D
ChrisR
1
catatan yang menarik di sini: php.net/manual/en/function.php-sapi-name.php adalah tergantung pada binary aktual yang dipanggil, Anda dapat menjalankan php dari baris perintah dan masih mendapatkan cgi-fgi
DAB
22

Ini akan selalu berhasil. (Jika versi PHP 4.2.0 atau lebih tinggi)

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

Yang membuatnya mudah digunakan di bagian atas skrip Anda:

<?php PHP_SAPI === 'cli' or die('not allowed');
Xeoncross
sumber
8
Cuplikan kedua Anda sepertinya tidak berurutan, saya kiraCLI or die('not allowed');
Madbreaks
1
@ Madbreak, saya menyatakan dua kegunaan terpisah. Saya mengasumsikan salah satu atau yang lain - tetapi jika Anda menggunakan keduanya maka CLI or die('not allowed');itu sempurna.
Xeoncross
Terima kasih telah mengklarifikasi, +1
Madbreaks
7
Which makes it easy to use at the top of your scriptstidak benar-benar membuatnya terdengar seperti dua kegunaan terpisah. Ya, saya seorang ahli nujum.
George Dimitriadis
9

Berikut ini adalah implementasi 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)));
}

Namun Drupal 8 merekomendasikan penggunaanPHP_SAPI === 'cli'

ya.teck
sumber
8

kupikir

$_SERVER['REMOTE_ADDR']

tidak akan diisi dari CLI.

Juga, semua kunci HTTP_ * di superglobal $ _SERVER tidak akan diisi dari CLI, atau lakukan dengan cara yang benar seperti yang baru saja disebutkan :-)

Vinko Vrsalovic
sumber
4

Halaman dokumentasi untuk php_sapi_name dengan jelas menyatakan cara kerjanya:

Mengembalikan string huruf kecil yang menjelaskan jenis antarmuka (API Server, SAPI) yang digunakan PHP ....

Meskipun tidak lengkap, nilai-nilai pengembalian yang mungkin termasuk aolserver, apache, apache2filter, apache2handler, caudium, cgi (hingga PHP 5.3), cgi-fcgi, cli, kontinuitas, embed, isapi, litespeed, milter, nsapi, phttpd, pi3web, roxen, thttpd, tux, dan webjames.

Saya tidak yakin mengapa hop tidak berpikir bahwa PHP adalah untuk programmer yang serius (Saya seorang programmer yang serius, dan saya menggunakan PHP setiap hari), tetapi jika dia ingin membantu memperjelas dokumentasi maka mungkin dia dapat mengaudit semua server web yang mungkin PHP dapat berjalan dan menentukan nama-nama semua jenis antarmuka yang mungkin untuk setiap server. Pastikan untuk tetap memperbarui daftar itu saat server web baru dan antarmuka ditambahkan.

Juga, Bobby berkata:

Saya tertarik mengapa dok. contoh memeriksa 3 karakter pertama, sedangkan deskripsi menyatakan string harus persis "CGI"

Deskripsi untuk contoh menyatakan:

Contoh ini memeriksa cgi substring karena mungkin juga cgi-fcgi.

Steve
sumber
Ah - entah saya sangat tidak patuh pada hari itu, atau contohnya telah diperbarui sejak saya membuat komentar itu. Sepenuhnya setuju dengan poin Anda tentang PHP, meskipun; bashing menjadi SANGAT melelahkan.
Bobby Jack