معالجة خيارات البرنامج
يمكن معالجة خيارات البرنامج باستخدام الدالة getopt()
، التي تعمل بصيغة مشابهة للأمر getopt
في معايير POSIX مع دعم إضافي للخيارات الطويلة ذات النمط GNU.
#!/usr/bin/php // تشير النقطتين إلى خيار يأخذ قيمة // تشير النقطتين المضاعفتين إلى قيمة يمكن إهمالها $shortopts = "hf:v::d"; // الخيارات الطويلة ذات النمط GNU غير مطلوبة $longopts = ["help", "version"]; $opts = getopt($shortopts, $longopts); // تُسند القيمة المنطقية false للخيارات التي ليس لها قيم، يجب التحقق من وجودها وليس صدقها if (isset($opts["h"]) || isset($opts["help"])) { fprintf(STDERR, "Here is some help!\n"); exit; } // تُستدعى الخيارات الطويلة مع شرطتين: "--version" if (isset($opts["version"])) { fprintf(STDERR, "%s Version 223.45" . PHP_EOL, $argv[0]); exit; } // يمكن استدعاء الخيارات ذات القيم بالشكل "-f foo" أو "-ffoo" أو "-f=foo" $file = ""; if (isset($opts["f"])) { $file = $opts["f"]; } if (empty($file)) { fprintf(STDERR, "We wanted a file!" . PHP_EOL); exit(1); } fprintf(STDOUT, "File is %s" . PHP_EOL, $file); // يمكن استدعاء الخيارات ذات القيم الافتراضية بالشكل "-v5" أو "-v=5" $verbosity = 0; if (isset($opts["v"])) { $verbosity = ($opts["v"] === false) ? 1 : (int)$opts["v"]; } fprintf(STDOUT, "Verbosity is %d" . PHP_EOL, $verbosity); // تُمرَّر الخيارات التي نستدعيها عدة مرات كمصفوفة $debug = 0; if (isset($opts["d"])) { $debug = is_array($opts["d"]) ? count($opts["d"]) : 1; } fprintf(STDOUT, "Debug is %d" . PHP_EOL, $debug); // لا توجد طريقة تلقائية عند getopt لمعالجة الخيارات غير المتوقعة
يمكن اختبار السكربت السابق بالشكل:
./test.php --help ./test.php --version ./test.php -f foo -ddd ./test.php -v -d -ffoo ./test.php -v5 -f=foo ./test.php -f foo -v 5 -d
لاحظ أنّ الطريقة الأخيرة لن تعمل لأنّ -v 5
غير صحيحة.
ملاحظة: يعدّ الأمر getopt
بدءًا من الإصدار PHP 5.3.0 مستقلًا عن نظام التشغيل ويعمل أيضًا على نظام ويندوز.
معالجة الوسيط
تُمرَّر الوسائط إلى البرنامج بطريقة مشابهة لمعظم اللغات ذات النمط C، إنّ $argc
عدد صحيح يعبّر عن عدد الوسائط متضمنةً اسم البرنامج و$argv
مصفوفة تتضمن وسائط البرنامج. العنصر الأول من $argv
هو اسم البرنامج.
#!/usr/bin/php printf("You called the program %s with %d arguments\n", $argv[0], $argc - 1); unset($argv[0]); foreach ($argv as $i => $arg) { printf("Argument %d is %s\n", $i, $arg); }
استدعاء التطبيق السابق باستخدام php example.php foo bar
(حيث يتضمن الملف example.php
الشيفرة السابقة) سيؤدي إلى الخرج التالي:
You called the program example.php with 2 arguments Argument 1 is foo Argument 2 is bar
لاحظ أنّ $argc
و$argv
هي متغيرات عامة وليست متغيرات ذات نطاق عام عالي، ويجب استيرادها إلى النطاق المحلي باستخدام الكلمة المفتاحية global
عندما نحتاج إلى استخدامها في دالة ما.
يُظهر هذا المثال كيف تُجمَّع الوسائط عندما نهرب باستخدام ""
أو \
.
مثال عن سكربت:
var_dump($argc, $argv);
سطر الأوامر:
$ php argc.argv.php --this-is-an-option three\ words\ together or "in one quote" but\ multiple\spaces\ counted\ as\ one int(6) array(6) { [0]=> string(13) "argc.argv.php" [1]=> string(19) "--this-is-an-option" [2]=> string(20) "three words together" [3]=> string(2) "or" [4]=> string(12) "in one quote" [5]=> string(34) "but multiple spaces counted as one" }
إذا نُفِّذ سكربت PHP باستخدام -r
:
$ php -r 'var_dump($argv);' array(1) { [0]=> string(1) "-" }
أو تُرسل الشيفرة عبر أنبوب في مجرى الدخل القياسي php
:
$ echo '<?php var_dump($argv);' | php array(1) { [0]=> string(1) "-" }
معالجة الدخل والخرج
إنّ الثوابت STDIN
وSTDOUT
وSTDERR
معرَّفة مسبقًا عند التنفيذ من واجهة سطر الأوامر (CLI)، وهي مقابض للملف يمكن أن نعدّها مكافئة لنتائج تنفيذ الأوامر التالية:
STDIN = fopen("php://stdin", "r"); STDOUT = fopen("php://stdout", "w"); STDERR = fopen("php://stderr", "w");
يمكن استخدام الثوابت في أي مكان يكون مقبض الملف القياسي فيه:
#!/usr/bin/php while ($line = fgets(STDIN)) { $line = strtolower(trim($line)); switch ($line) { case "bad": fprintf(STDERR, "%s is bad" . PHP_EOL, $line); break; case "quit": exit; default: fprintf(STDOUT, "%s is good" . PHP_EOL, $line); break; } }
يمكن استخدام عناوين المجرى المضمَّن المُشار إليها سابقًا php://stdin
وphp://stdout
وphp://stderr
مكان أسماء الملفات في معظم الحالات:
file_put_contents('php://stdout', 'This is stdout content'); file_put_contents('php://stderr', 'This is stderr content'); // فتح المقبض والكتابة عدة مرات $stdout = fopen('php://stdout', 'w'); fwrite($stdout, 'Hello world from stdout' . PHP_EOL); fwrite($stdout, 'Hello again'); fclose($stdout);
يمكن أن تستخدم أيضًا الدالة readline() كبديل للدخل وتستخدم echo
أو print
أو أي دالة من دوال طباعة السلسلة النصية كبديل للخرج.
$name = readline("Please enter your name:"); print "Hello, {$name}.";
الشيفرات المُعادة
يمكن استخدام البنية exit
لتمرير شيفرة معادة إلى بيئة التنفيذ.
#!/usr/bin/php if ($argv[1] === "bad") { exit(1); } else { exit(0); }
ستُرجَع شيفرة الخروج 0 بشكلٍ افتراضي إذا لم تُمرَّر قيمة أي أنّ exit
نفس exit(0)
وبما أنّ exit
ليست دالة فإنّ الأقواس غير ضرورية إذا لم تُمرَّر شيفرة معادة.
يجب أن تكون الشيفرات المُعادة في المجال بين 0 و254 (الشيفرة 255 محجوزة من قِبَل PHP ويجب عدم استخدامها)، اصطلاحًا إنّ الخروج بالشيفرة المُرجعة 0 تُخبر البرنامج المُستدعي أنّ سكربت PHP نُفِّذ بنجاح أما الشيفرة المرجعية غير الصفرية تُخبر البرنامج المستدعي بحدوث حالة خطأ محددة.
قصر تنفيذ السكربت على سطر الأوامر
يُرجع كل من الدالة php_sapi_name() والثابت PHP_SAPI
نوع الواجهة (واجهة برمجة تطبيقات الخادم Server API
) التي تستخدمها PHP، ويمكن استخدامها لقصر تنفيذ السكربت على سطر الأوامر عن طريق التحقق فيما إذا كان خرج الدالة يساوي cli
.
if (php_sapi_name() === 'cli') { echo "Executed from command line\n"; } else { echo "Executed from web browser\n"; }
الدالة drupal_is_cli()
هي مثال عن دالة تكتشف فيما إذا كان السكربت قد نُفِّذ من سطر الأوامر:
function drupal_is_cli() { return (!isset($_SERVER['SERVER_SOFTWARE']) && (php_sapi_name() == 'cli' || (is_numeric($_SERVER['argc']) && $_SERVER['argc'] > 0))); }
الاختلافات السلوكية في سطر الأوامر
تعرض PHP عند التنفيذ من CLI بعض السلوكيات المختلفة عن السلوكيات عند التنفيذ على خادم ويب، يجب أن تتذكر هذه السلوكيات خاصةً في حالة تنفيذ نفس السكربت في البيئتين.
-
لا يتغير المجلد عند التنفيذ على خادم ويب بل يبقى مجلد العمل الحالي للسكربت نفسه دائمًا، تفترض الشيفرة
require("./stuff.inc");
أنّ الملف في نفس مجلد السكربت، أما في سطر الأوامر فإنّ مجلد العمل الحالي هو المجلد الذي يُستدعى منه السكربت، يجب أن تستخدم السكربتات التي ستُستدعى من سطر الأوامر مسارات مطلقة. (لاحظ أنّ الثوابت السحرية__DIR__
و__FILE__
تبقى تعمل كما هو متوقع وتُرجع موقع السكربت). -
لا يوجد مخزن مؤقت للخرج، القيم الافتراضية لموجهات الملف
php.ini
output_buffering
وimplicit_flush
هيfalse
وtrue
على الترتيب. ويبقى المخزن المؤقت متوفرًا لكن يجب تمكينه بشكلٍ صريح وإلا سيُعرض الخرج دائمًا في الوقت الحقيقي. -
لا يوجد قيد زمني، يُضبط الموجه
max_execution_time
في الملفphp.ini
إلى القيمة صفر لذا لن ينتهي وقت تنفيذ السكربتات بشكلٍ افتراضي. -
لا توجد أخطاء HTML، إذا مكّنت الموجّه
html_errors
في ملفphp.ini
سيتجاهله سطر الأوامر. -
يمكن تحميل ملفات
php.ini
مختلفة، إذا كنت تستخدم PHP من CLI يمكنك تحميل ملفاتphp.ini
مختلفة وهذا غير متاح عند التنفيذ على خادم ويب، يمكنك أن تعرف ما هو الملف المستخدم بتنفيذ الأمرphp --ini
.
تنفيذ السكربت
في كل من لينوكس/يونكس أو ويندوز يمكن تمرير الملف كوسيط إلى PHP القابلة للتنفيذ مع خيارات ووسائط السكربت:
php ~/example.php foo bar c:\php\php.exe c:\example.php foo bar
تمرر الشيفرة السابقة الوسائط foo
وbar
إلى الملف example.php
.
الطريقة المفضلة لتنفيذ السكربتات في لينوكس/يونكس هي استخدام Shebang (سطر يبدأ بالسلسلة النصية " #! ") مثل #!/usr/bin/env php
في السطر الأول من الملف وضبط البت القابل للتنفيذ على الملف، بفرض أنّ السكربت في مسارك يمكنك عندها استدعاؤه مباشرةً:
example.php foo bar
إنّ استخدام /usr/bin/env php
يجعل من الممكن العثور على PHP القابلة للتنفيذ باستخدام PATH
. وفقًا لكيفية تثبيت PHP قد لا تكون موجودة في نفس المكان (مثل /usr/bin/php
أو /usr/local/bin/php
) على عكس env
المتوفرة عادةً في /usr/bin/env
.
في ويندوز قد تحصل على نفس النتيجة بإضافة مجلد PHP والسكربت الخاص بك إلى PATH
وتعديل PATHEXT
ليسمح باكتشاف .php
باستخدام PATH
، الاحتمال الآخر هو إضافة ملف باسم example.bat
أو example.cmd
في نفس المجلد الموجود به سكربت PHP وكتابة هذا السطر فيه:
c:\php\php.exe "%~dp0example.php" %*
أو إذا أضفت مجلد PHP داخل PATH
:
php "%~dp0example.php" %*
حالات متقدمة لاستخدام getopt()
يظهر هذا المثال سلوك getopt
عندما يكون دخل المستخدم غير شائع، محتويات الملف getopt.php
:
var_dump( getopt("ab:c::", ["delta", "epsilon:", "zeta::"]) );
سطر أوامر الصدفة:
$ php getopt.php -a -a -bbeta -b beta -cgamma --delta --epsilon --zeta --zeta=f -c gamma array(6) { ["a"]=> array(2) { [0]=> bool(false) [1]=> bool(false) } ["b"]=> array(2) { [0]=> string(4) "beta" [1]=> string(4) "beta" } ["c"]=> array(2) { [0]=> string(5) "gamma" [1]=> bool(false) } ["delta"]=> bool(false) ["epsilon"]=> string(6) "--zeta" ["zeta"]=> string(1) "f" }
يمكننا أن نلاحظ من المثال السابق:
-
تحمل الخيارات الفردية (بدون نقطتان) دائمًا القيمة المنطقية
false
إذا مُكِّنت. -
إذا كُرِّر خيار ما فإنّ قيمة خرج
getopt
ستصبح مصفوفة. - تقبل خيارات الوسيط المطلوب (بنقطتين) فراغ واحد أو عدم وجود فراغ (مثل خيارات الوسيط الاختيارية) كفاصل.
- بعد وجود وسيط واحد لا يمكن ربطه بأي خيار فإنّ الخيارات التالية لن تُربط أيضًا.
تشغيل خادم ويب مدمج
أصبحت PHP بدءًا من الإصدار PHP 5.4 تأتي مع خادم مدمج، يمكن استخدامه لتنفيذ تطبيق بدون الحاجة لتثبيت أي خادم http مثل nginx
أو apache
، صُمم الخادم المدمج في بيئة المتحكم فقط لأهداف التطوير والاختبار، يمكن تنفيذه باستخدام الأمر php -S
ولاختباره ننشئ الملف index.php
ونكتب فيه:
<?php echo "Hello World from built-in PHP server";
وننفذ الأمر:
php -S localhost:8080
يجب أن تكون الآن قادرًا على رؤية المحتوى في المتصفح، للتحقق من ذلك انتقل إلى المسار http://localhost:8080
، ويجب أن يؤدي كل وصول إلى مدخل سجل يُكتب في الطرفية (Terminal).
[Mon Aug 15 18:20:19 2016] ::1:52455 [200]: /
ترجمة -وبتصرف- للفصل [Command Line Interface (CLI)] من كتاب PHP Notes for Professionals book
اقرأ أيضًا
- المقال التالي: اصطلاحات ومواضيع متفرقة مهمة لكل مبرمج PHP
- المقال السابق: ملاحظات حول استعمال بروتوكول IMAP في PHP
أفضل التعليقات
لا توجد أية تعليقات بعد
انضم إلى النقاش
يمكنك أن تنشر الآن وتسجل لاحقًا. إذا كان لديك حساب، فسجل الدخول الآن لتنشر باسم حسابك.