ویژگی تصویر

متد ob_implicit_flush() در PHP

  /  PHP   /  متد ob_implicit_flush() در PHP
بنر تبلیغاتی الف
آموزش PHP

در PHP خروجی پیش‌فرض به صورت بافر شده ارسال می‌شود؛ یعنی متن‌هایی که با echo، print یا خروجی‌های دیگر تولید می‌شوند ابتدا در بافر نگهداری شده و سپس در یک نقطه مناسب (مثلاً پایان اسکریپت یا زمانی که بافر پر شود) به مرورگر یا کلاینت ارسال می‌گردند. متد ob_implicit_flush() ابزاری است که رفتار این بافر را تغییر می‌دهد و امکان ارسال فوری (implicit flush) را فراهم می‌کند.

تعریف و سینتکس

void ob_implicit_flush ([ bool $enable = true ] )

این تابع اگر بدون آرگومان فراخوانی شود، implicit flush را فعال می‌کند. با ارسال false می‌توانید آن را غیرفعال کنید. بازگرداندنی ندارد (void).

چه چیزی را تغییر می‌دهد؟

  • با فعال کردن implicit flush، PHP پس از هر دستور تولید خروجی سعی می‌کند خروجی را فوراً به لایه‌های پایین‌تر ارسال کند.
  • توجه کنید که این «فوراً» به معنی رسیدن به مرورگر نیست؛ وب‌سرور، ماژول‌های فشرده‌سازی و خود مرورگر ممکن است هنوز خروجی را بافر کنند.

تفاوت بین ob_implicit_flush، ob_flush و flush

تابععملکرد
ob_implicit_flush()تعیین می‌کند که PHP پس از تولید خروجی به‌طور خودکار فراخوانی ob_flush() را انجام دهد یا خیر.
ob_flush()محتوای بافر خروجی PHP (output buffer) را به لایه بعدی منتقل می‌کند ولی ممکن است توسط وب‌سرور بافر شود.
flush()سعی می‌کند هر چیزی که به سمت کلاینت آماده شده را به لایه‌های پایین‌تر ارسال کند (بعد از ob_flush معمولاً استفاده می‌شود).

مثال پایه‌ای

<?php
// فعال کردن implicit flush
ob_implicit_flush(true);

// جلوگیری از بافرهای اضافی پی‌اچ‌پی
while (ob_get_level() > 0) {
    ob_end_flush();
}

echo "شروع عملیات...n";
for ($i = 1; $i <= 5; $i++) {
    echo "مرحله $i در حال انجام...n";
    sleep(1);
}
echo "پایانn";
?>

در این مثال ob_implicit_flush(true) تنظیم شده و سپس با حلقه ob_end_flush() هر بافر خروجی فعال بسته می‌شود تا خروجی مستقیم‌تری داشته باشیم. پس از آن در هر تکرار پیغام ارسال می‌شود و به‌صورت تقریبی باید هر ثانیه به کلاینت برسد — البته اگر وب‌سرور یا فشرده‌سازی جلوی ارسال را نگیرد.

مثال برای Server-Sent Events (SSE)

<?php
// برای SSE
header('Content-Type: text/event-stream');
header('Cache-Control: no-cache');

// غیرفعال کردن فشرده‌سازی
@ini_set('zlib.output_compression', 0);
if (function_exists('apache_setenv')) {
    @apache_setenv('no-gzip', '1');
}

ob_implicit_flush(true);
while (ob_get_level() > 0) {
    ob_end_flush();
}

$counter = 0;
while (true) {
    $counter++;
    echo "data: {"time": "".date('H:i:s')."", "count": $counter}nn";
    // ob_flush و flush برای اطمینان
    if (ob_get_length()) ob_flush();
    flush();
    sleep(1);
}
?>

این نمونه برای ارسال رویدادهای پیوسته به مرورگر است. توجه داشته باشید که باید فشرده‌سازی خروجی را خاموش کنید و هدر مناسب SSE را قرار دهید تا مرورگر بتواند داده‌ها را آنی دریافت کند. استفاده از ob_flush() و flush() همراه با ob_implicit_flush تضمینی است برای کاهش بافرینگ در لایه PHP، اما گلوگاه‌های دیگری (مثل FastCGI، Nginx buffering) ممکن است وجود داشته باشد.

نکات مهم و محدودیت‌ها

  • ob_implicit_flush فقط رفتا‌ر درونی PHP را تغییر می‌دهد؛ وب‌سرور (Apache، Nginx، FPM)، پروکسی و مرورگر ممکن است خروجی را بافر کنند.
  • ماژول‌های فشرده‌سازی مثل zlib یا mod_deflate می‌توانند باعث شوند داده‌های کوچک انباشته شوند تا بلوک فشرده‌سازی کامل شود.
  • در FastCGI/PHP-FPM، تنظیماتی مانند output_buffering و fastcgi_buffering در وب‌سرور/پیکربندی می‌توانند مانع ارسال فوری شوند.
  • برای کاربردهای CLI یا ترمینال، ob_implicit_flush غالباً بهتر جواب می‌دهد چون لایه‌های میانی کمتر است.

موارد استفاده عملی

  • اسکریپت‌های زمان‌بَر که می‌خواهند وضعیت پیشرفت (progress) را به مرورگر ارسال کنند.
  • Server-Sent Events (SSE) ساده یا نگاشت به WebSocket در برخی پیاده‌سازی‌ها.
  • اجرای پردازش‌های پس‌زمینه همراه با گزارش لحظه‌ای برای کاربر.
  • سرویس‌های CLI که نیاز به نمایش آنی خروجی دارند.

بهترین شیوه‌ها و توصیه‌ها

  • اگر می‌خواهید خروجی آنی به مرورگر برسد، علاوه بر ob_implicit_flush، حتماً فشرده‌سازی را غیرفعال کنید و تنظیمات وب‌سرور را بررسی نمایید.
  • از ارسال هدرهای مناسب و استفاده از تکنیک‌هایی مثل chunked encoding بهره ببرید (تنظیم Content-Length به‌صورت ثابت معمولاً مانع ارسال تدریجی می‌شود).
  • برای تست، از ابزارهایی مثل curl یا یک ترمینال برای مشاهده دریافت بایت‌ها استفاده کنید؛ مرورگرها ممکن است رفتارهای متفاوتی در پردازش partial response داشته باشند.
  • در بسیاری از موارد بهتر است به‌جای تلاش برای دورزدن بافرها، از پروتکل‌های مناسب (SSE، WebSocket) و پیاده‌سازی سمت سرور/وب‌سرور پشتیبانی‌شده استفاده کنید.

جمع‌بندی

ob_implicit_flush() تابعی ساده اما مفید برای کنترل رفتار بافر خروجی PHP است. این متد برای مواردی که نیاز به ارسال آنی خروجی از سمت اسکریپت وجود دارد مناسب است، اما برای دریافت خروجی واقعی در کلاینت باید سایر لایه‌های سیستم را هم در نظر گرفت. شناخت تعامل میان ob_flush، flush، تنظیمات ini و رفتار وب‌سرور برای موفقیت در پیاده‌سازی‌های real-time ضروری است.

در صورت نیاز می‌توان نمونه‌هایی تخصصی‌تر برای محیط‌های خاص (PHP-FPM + Nginx، Apache mod_php، یا CLI) تهیه کرد تا راه‌حل‌هایی کاربردی برای هر سناریو ارائه شود.

آیا این مطلب برای شما مفید بود ؟

خیر
بله
موضوعات شما در انجمن: