ویژگی تصویر

تابع stream_context_set_params() در PHP

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

تابع stream_context_set_params() یکی از توابع مفید در مدیریت جریان‌های (streams) PHP است که به شما امکان می‌دهد پارامترهای سطح بالایی برای یک context جریان تنظیم کنید. این تابع در سنیاریوهایی کاربردی است که نیاز به تغییر رفتار عمومی یک جریان (مثل تعیین callback اطلاع‌رسانی یا مشخص کردن قابل‌جابه‌جایی بودن) دارید. در این مقاله به صورت کامل کاربردها، نمونه‌های عملی، نکات پیشرفته و محدودیت‌ها را توضیح می‌دهیم.

امضای تابع و مقدار بازگشتی

تابعامضابازگشت
stream_context_set_paramsbool stream_context_set_params(resource $context_or_stream, array $params)TRUE در صورت موفقیت، FALSE در صورت شکست

پارامتر اول می‌تواند یا یک resource context باشد که با stream_context_create ساخته شده یا یک resource جریان مانند نتیجه fopen(). پارامتر دوم آرایه‌ای از کلید/مقدارها است که بسته به wrapper یا پیاده‌سازی می‌تواند استفاده یا نادیده گرفته شوند.

پارامترهای رایج

  • notification: یک callback که از رویدادهای جریان (مانند پیشرفت دانلود، تغییر سایز فایل، ریدایرکت و …) اطلاع می‌دهد. این معمولاً یکی از مهم‌ترین استفاده‌هاست.
  • seekable: بولی که مشخص می‌کند آیا جریان قابل seek است یا خیر (بعضی از wrapperها این را رعایت می‌کنند).
  • پارامترهای خاص: برخی wrapperها پارامترهای اختصاصی دیگری را می‌پذیرند — اگر ناشناس باشند، نادیده گرفته می‌شوند.

نکته مهم: پارامترهای عمومی context (مانند گزینه‌های HTTP) با stream_context_set_option() تنظیم می‌شوند، نه با این تابع. stream_context_set_params برای پارامترهای سطح جریان استفاده می‌شود.

نمونه: استفاده از callback اطلاع‌رسانی

 0) {
                $pct = round(($bytes_transferred / $bytes_max) * 100, 2);
                echo "Progress: $pct% ($bytes_transferred / $bytes_max)n";
            } else {
                echo "Progress: $bytes_transferred bytes transferredn";
            }
            break;
        case STREAM_NOTIFY_FAILURE:
            echo "A failure occurred: $messagen";
            break;
    }
}

// ساخت context و تنظیم پارامتر notification
$ctx = stream_context_create();
stream_context_set_params($ctx, ['notification' => 'my_stream_notify']);

// باز کردن یک URL با استفاده از context
$fp = fopen('http://example.com/largefile.bin', 'r', false, $ctx);
if ($fp) {
    while (!feof($fp)) {
        echo fread($fp, 8192);
    }
    fclose($fp);
}
?>

توضیح: در این مثال ابتدا یک callback با نام my_stream_notify تعریف شده که انواع مختلف اعلان‌ها را هندل می‌کند (مانند اتصال، اندازه فایل و پیشرفت). سپس یک context ایجاد می‌کنیم و با stream_context_set_params کلید notification را به callback متصل می‌کنیم. در نهایت با fopen و عبور context، جریان با این callback اطلاع‌رسانی خواهد کرد. توجه داشته باشید که wrapperها ممکن است همه نوع اعلان را تولید نکنند؛ بنابراین تعداد و نوع اعلان‌ها بستگی به پروتکل و پیاده‌سازی دارد.

چند نکته در مورد callback اطلاع‌رسانی

  • امضای تابع callback بسته به نسخه PHP ثابت نیست ولی معمولاً شامل پارامترهایی مانند notification_code، severity، message، message_code، bytes_transferred و bytes_max است. برای اطمینان امضای دقیق را در مستندات PHPِ نسخه خود بررسی کنید.
  • مثال بالا از ثوابت پیش‌فرضی مثل STREAM_NOTIFY_PROGRESS و STREAM_NOTIFY_FILE_SIZE_IS استفاده می‌کند — این ثوابت در PHP تعریف شده‌اند.

موارد کاربرد و سناریوهای واقعی

  • نمایش نوار پیشرفت دانلود یا آپلود در رابط کاربری زمانی که از توابع stream استفاده می‌کنید.
  • گرفتن اطلاع از ریدایرکت‌ها، تغییر نوع MIME یا خطاهای لایه پروتکل هنگام کار با HTTP/FTP.
  • غیرقابل‌قابل‌جابه‌جایی کردن یک جریان برای جلوگیری از اجرای توابع seek در مصادر خاص.
  • جمع‌آوری لاگ‌های دقیق از وضعیت اتصال و انتقال داده‌ها برای تحلیل و دیباگ شبکه.

نکات عملکردی و محدودیت‌ها

  • بسیاری از wrapperها تنها تعداد محدودی از اعلان‌ها را تولید می‌کنند یا اصلاً اعلان تولید نمی‌کنند. بنابراین نباید روی اعلان‌ها به عنوان منبع حقیقت قطعی حساب باز کنید.
  • برای کنترل طولانی‌مدت timeout بهتر است از stream_set_timeout() روی resource باز شده استفاده کنید. stream_context_set_params معمولاً برای timeout عمومی context کاربرد ندارد.
  • برای نیازهای پیشرفته شبکه (مثل احراز هویت پیچیده، کوکی‌های پیشرفته یا مدیریت کانکشن) معمولاً cURL ابزار مناسب‌تری است.
  • callback باید سبک و کم‌هزینه باشد؛ زیرا فراخوانی مکرر آن (مثلاً در رویدادهای progress) می‌تواند بر عملکرد خواندن/نوشتن تأثیر بگذارد.

مثال بهبود: محدود کردن فراخوانی‌ها برای به‌روزرسانی UI

<?php
$last_update = 0;
function throttle_notify($notification_code, $severity, $message, $message_code, $bytes_transferred, $bytes_max) {
    global $last_update;
    $now = microtime(true);
    // تنها هر 0.5 ثانیه یک‌بار بروزرسانی نمایش دهد
    if ($now - $last_update  0) {
            $pct = round(($bytes_transferred / $bytes_max) * 100, 1);
            echo "Progress: $pct%n";
        } else {
            echo "Transferred: $bytes_transferred bytesn";
        }
    }
}
?>

توضیح: در این نسخه یک throttle ساده اضافه شده تا callback خیلی مکرر اجرا نشود و بار پردازشی روی برنامه کاهش یابد. این تکنیک برای رابط‌های کاربری یا لاگ‌نویسی مفید است.

دیباگ و عیب‌یابی

  • اگر callback فراخوانی نمی‌شود، اطمینان حاصل کنید wrapper مورد استفاده اعلان‌ها را تولید می‌کند (مثلاً برخی پیاده‌سازی‌های fopen روی بعضی سرورها اعلان progress را تولید نمی‌کنند).
  • مطمئن شوید context صحیح به تابع fopen یا stream_socket_client داده شده است و تابع stream_context_set_params با موفقیت TRUE برگردانده است.
  • برای مشاهده خطاها، error_reporting و display_errors را فعال کنید یا از فایلی لاگ بگیرید.

جمع‌بندی و توصیه‌های حرفه‌ای

stream_context_set_params() ابزاری سبک و مفید برای کنترل رفتار کلی جریان‌ها در PHP است، به‌ویژه زمانی که نیاز به اطلاع‌رسانی رویدادها دارید. اما برای کنترل‌های شبکه‌ای پیشرفته‌تر یا نیاز به پایداری و عملکرد بالا، بررسی استفاده از cURL یا کتابخانه‌های HTTP سطح بالا توصیه می‌شود. از callbackها برای لاگینگ و نمایش پیشرفت استفاده کنید، اما آنها را به‌صورت بهینه و با محافظت در برابر اجرای مکرر پیاده‌سازی کنید.

برای موارد دقیق‌تر و فهرست کامل ثوابت و امضای callback، مستندات رسمی PHP مربوط به stream_notification_callback و stream_context_set_params را در نسخه PHP خود مطالعه کنید.

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

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