تابع stream_isatty() در PHP
در برنامهنویسی خط فرمان (CLI) گاهی لازم است بدانیم که جریان ورودی/خروجی (stream) متصل به یک ترمینال تعاملی (TTY) است یا خیر. تابع stream_isatty() در PHP دقیقاً برای این منظور طراحی شده است: تشخیص اینکه آیا یک resource از نوع stream به یک کنسول/ترمینال واقعی متصل است یا خیر.
امضا و مقدار بازگشتی
امضا:
bool stream_isatty ( resource $stream )توضیح: این تابع یک مقدار بولی برمیگرداند — true اگر stream به یک TTY متصل باشد و false اگر نباشد یا اگر پارامتر نامعتبر باشد.
چه زمانی از stream_isatty استفاده کنیم؟
- فعال/غیرفعال کردن رنگها یا فرمتدهی ANSI در خروجی بر اساس اینکه خروجی به صفحهنمایش متصل است یا درون فایل/پایپ ریدایرکت شده.
- نمایش یا پنهان کردن نوار پیشرفت (progress bar) هنگام اجرای اسکریپتها.
- تصمیمگیری در مورد خواندن تعاملی از STDIN یا اجرا در حالت غیرتعاملی (مثلاً زمانی که ورودی از یک فایل یا piped داده میشود).
- نوشتن ابزارهای CLI که با محیطهای تعاملی و غیرتعامل کار میکنند و نیاز به تطبیق رفتار دارند.
مثال ساده: رنگ دهی شرطی
<?php
if (stream_isatty(STDOUT)) {
// اگر خروجی به ترمینال متصل است، از رنگ استفاده میکنیم
echo "33[32mSuccess!33[0mn";
} else {
// در غیر این صورت رنگها را نادیده میگیریم (مثلاً هنگام ریدایرِکت به فایل)
echo "Success!n";
}
?>توضیح: در این مثال ابتدا بررسی میکنیم که STDOUT به یک ترمینال متصل است یا خیر. در حالت true خروجی را با کدهای ANSI رنگی چاپ میکنیم و در حالت false متن ساده مینویسیم تا فایل/لاگ خوانا بماند.
مثال: تشخیص حالت تعاملی برای خواندن از STDIN
<?php
$stdin = fopen('php://stdin', 'r');
if (is_resource($stdin) && stream_isatty($stdin)) {
echo "Please enter your name: ";
$name = trim(fgets($stdin));
echo "Hello, $namen";
} else {
// ورودی از فایل یا pipe آمده است
$data = stream_get_contents($stdin);
// پردازش غیرتعاملی
echo "Received data length: ".strlen($data)."n";
}
?>توضیح: این کد تفاوت بین حالت تعاملی و غیرتعامل را تشخیص میدهد. اگر STDIN به ترمینال متصل باشد از fgets برای خواندن تعاملی استفاده میکند؛ در غیر این صورت کل دادهها از stream خوانده و پردازش میشوند.
نکات عملی و ملاحظات سازگاری
- تابع از PHP 7.2 در هسته در دسترس است. قبل از آن یا در برخی محیطها ممکن است لازم باشد از کتابخانهها یا پلیفیلها استفاده کنید.
- در محیطهای Web SAPI (مثل Apache یا FPM) معمولاً streamها به TTY متصل نیستند؛ بنابراین نتیجه همیشه false خواهد بود.
- رفتار در ویندوز ممکن است متفاوت باشد: پیادهسازی سیستمعامل تعیینکننده است و برخی ترمینالها (مثل کنسولهای جایگزین یا شبیهسازهای ANSI) ممکن است وضعیت TTY را متفاوت گزارش دهند.
- پارامتر باید یک resource معتبر باشد؛ توصیه میشود قبل از فراخوانی تابع از is_resource() یا is_stream اطمینان حاصل کنید تا از هشدارهای ناخواسته جلوگیری شود.
مثال ایمن با بررسی اعتبار resource
<?php
function isInteractive($stream) {
if (!is_resource($stream)) {
return false;
}
if (!function_exists('stream_isatty')) {
// fallback ساده: در صورت عدم وجود تابع، میتوانیم بررسیهای محیطی انجام دهیم
return getenv('TERM') !== false && getenv('TERM') !== 'dumb';
}
return stream_isatty($stream);
}
if (isInteractive(STDOUT)) {
echo "Interactive terminaln";
} else {
echo "Non-interactiven";
}
?>توضیح: این تابع کمکی ابتدا اعتبار resource را بررسی میکند، سپس وجود تابع stream_isatty را کنترل میکند و در صورت عدم وجود یک fallback ساده بر پایه متغیر محیطی TERM ارائه میدهد. توجه کنید که fallback کامل و قطعی نیست اما در محیطهای قدیمی کمککننده است.
جدول خلاصه—چه انتظاری داشته باشیم
| شرایط | stream_isatty | نتیجه معمول |
|---|---|---|
| اجرای در ترمینال محلی (مثلاً php script.php) | STDOUT | true |
| ریدایرکت خروجی به فایل (php script.php > out.txt) | STDOUT | false |
| پایپ کردن خروجی (php script.php | less) | STDOUT | false |
| اجرای در وب (Apache/FPM) | php://output یا streamهای مشابه | false |
تضادها و راهکارهای رایج
- کتابخانههای معروف CLI (مانند Symfony Console) از تشخیص TTY برای فعالسازی رنگ و تعامل استفاده میکنند. وقتی میخواهید با این کتابخانهها سازگار باشید، از stream_isatty برای تشخیص رفتار استفاده کنید.
- در ویندوز و برخی ترمینالهای مدرن، ممکن است برای پشتیبانی کامل از رنگ نیاز به فعالسازی دستی کدهای ANSI یا استفاده از کتابخانههایی باشد که ترمینال را شناسایی و آمادهسازی میکنند.
- برای تست در CI/CD یا محیطهای headless، معمولاً streamها TTY نیستند؛ بنابراین حین نوشتن تستها به این نکته توجه کنید تا خروجیها مطابق انتظار باشند.
جمعبندی
تابع stream_isatty() ابزار ساده و مؤثری برای تشخیص اینکه آیا یک stream متصل به ترمینال تعاملی است یا خیر فراهم میکند. این تابع در طراحی ابزارهای CLI، مدیریت رنگ و تعامل با کاربر کاربرد فراوانی دارد. برای استفاده صحیح، همواره اعتبار منبع را بررسی کنید، با توجه به SAPI و سیستمعامل ملاحظات سازگاری را در نظر بگیرید و در صورت نیاز از راهکارهای fallback منطقی استفاده کنید.
آیا این مطلب برای شما مفید بود ؟



