تابع stream_filter_prepend() در PHP
تابع stream_filter_prepend() یکی از ابزارهای قوی در اکوسیستم Streamهای PHP است که به شما اجازه میدهد یک فیلتر را در ابتدا (prepend) زنجیرهٔ فیلترهای یک stream قرار دهید. این امکان برای تغییر، فشردهسازی، رمزنگاری یا لاگگیری جریان دادهها قبل از پردازش نهایی بسیار مفید است.
چرا و چه زمانی از stream_filter_prepend استفاده کنیم؟
- هنگامی که میخواهید مطمئن شوید فیلتر خاصی زودتر از بقیه اجرا شود (مثلاً رمزگشایی یا حذف headerها).
- وقتی میخواهید خروجی تولیدشده توسط دیگر فیلترها را پیشپردازش کنید.
- برای اضافه کردن فیلترهای لاگ، آنالیز یا تبدیل متن بدون تغییر منبع اصلی فایل.
امضای تابع و پارامترها
امضای تابع:
resource|false stream_filter_prepend(resource $stream, string $filtername, int $read_write = STREAM_FILTER_READ, mixed $params = null)توضیح پارامترها:
- $stream: منبع stream مانند نتیجه fopen یا php://memory.
- $filtername: نام فیلتر (مثلاً “string.toupper” یا نام ثبتشدهٔ شما).
- $read_write: جهت فیلتر — STREAM_FILTER_READ یا STREAM_FILTER_WRITE یا ترکیبی.
- $params: پارامتر دلخواه که به فیلتر ارسال میشود (در صورت استفاده از فیلترهای کاربر).
مفاهیم کلیدی: ترتیب فیلترها و خروجی
ترتیب فیلترها مهم است. فیلترهایی که prepend میشوند زودتر اجرا میشوند نسبت به آنهایی که قبلاً به stream اضافه شدهاند. برای ترکیب رفتارها از stream_filter_append هم استفاده میشود که فیلتر را در انتهای زنجیره قرار میدهد.
| عمل | اثر |
|---|---|
| stream_filter_prepend | فیلتر در ابتدای زنجیره قرار میگیرد (اول اجرا میشود) |
| stream_filter_append | فیلتر در انتهای زنجیره قرار میگیرد (آخر اجرا میشود) |
مثال عملی: فیلتر داخلی string.toupper
<?php
$fp = fopen('php://temp', 'rw+');
fwrite($fp, "hello worldn");
rewind($fp);
// prepend built-in filter to convert text to uppercase on read
stream_filter_prepend($fp, 'string.toupper', STREAM_FILTER_READ);
rewind($fp);
echo stream_get_contents($fp);
?>در این مثال، ما یک stream موقتی ساختیم و با استفاده از stream_filter_prepend فیلتر داخلی string.toupper را برای عملیات خواندن (READ) اضافه کردیم. بنابراین وقتی محتوا را میخوانیم، تمام حروف به حروف بزرگ تبدیل شدهاند. این مثال نشان میدهد که prepend تضمین میکند فیلتر قبل از دیگر پردازشها اجرا شود.
مثال پیشرفته: ثبت و استفاده از یک فیلتر کاربر
<?php
class PrefixFilter extends php_user_filter {
public function filter($in, $out, &$consumed, $closing) {
while ($bucket = stream_bucket_make_writeable($in)) {
$bucket->data = "[PREFIX] " . $bucket->data;
$consumed += $bucket->datalen;
stream_bucket_append($out, $bucket);
}
return PSFS_PASS_ON;
}
}
stream_filter_register('add.prefix', 'PrefixFilter');
$fp = fopen('php://temp', 'rw+');
stream_filter_prepend($fp, 'add.prefix', STREAM_FILTER_WRITE);
fwrite($fp, "Line1nLine2n");
rewind($fp);
echo stream_get_contents($fp);
?>توضیح: در این کد یک کلاس فیلتر کاربر تعریف شده که از php_user_filter ارثبری میکند. متد filter هر بدنهٔ (bucket) ورود را میگیرد، قبل از دادهها رشتهٔ “[PREFIX] ” را میافزاید و سپس در خروجی قرار میدهد. سپس فیلتر با استفاده از stream_filter_register ثبت و با stream_filter_prepend به stream هنگام نوشتن متصل میشود. نتیجهٔ خواندن نشان خواهد داد که هر خط با پیشوند اضافه شده است.
نکات فنی در پیادهسازی فیلترهای کاربر
- درون متد filter باید از stream_bucket_make_writeable و stream_bucket_append استفاده شود.
- مقادیر بازگشتی باید یکی از ثابتهای PSFS_* باشد: PSFS_FEED_ME، PSFS_PASS_ON، PSFS_ERR_FATAL.
- پارامترهای اضافی از $params قابل دریافت در $this->params هستند.
- برای عملیات پیچیدهتر بهتر است از بافرهای داخلی استفاده و از تغییر مکرر دادهها در هر bucket خودداری کنید تا کارایی بهتر شود.
مقایسه prepend و append — چه موقع کدام را انتخاب کنیم
- اگر میخواهید دادهها قبل از هر فیلتر دیگری تغییر کنند (مثلاً رمزگشایی قبل از لاگ)، از prepend استفاده کنید.
- اگر میخواهید دادهها بعد از همهٔ تبدیلها نهایی شوند (مثلاً کدگذاری نهایی)، از append استفاده کنید.
مثال تفاوت ترتیب فیلترها
<?php
$fp = fopen('php://temp', 'rw+');
fwrite($fp, "testn");
rewind($fp);
// prepend makes this run first on read
stream_filter_prepend($fp, 'string.toupper', STREAM_FILTER_READ);
// append makes this run after existing filters on read
stream_filter_append($fp, 'string.rot13', STREAM_FILTER_READ);
rewind($fp);
echo stream_get_contents($fp);
?>در این حالت، ترتیب اجرای فیلترها تعیینکنندهٔ خروجی نهایی است: ابتدا string.toupper سپس string.rot13 اجرا خواهد شد (با توجه به prepend و append). ترتیب ممکن است بر نتیجهٔ تبدیلهای پیچیده تاثیرگذار باشد.
موارد احتیاط و بهینهسازی
- در streams با ترافیک بالا، فیلترهای پیچیده ممکن است بار CPU را افزایش دهند — سعی کنید پردازش را در صورت امکان به بلوکهای بزرکتر منتقل کنید.
- در فیلترهای خواندن/نوشتن دقت کنید که بافرها را به درستی مدیریت کنید تا از مصرف بیشازحد حافظه جلوگیری شود.
- در موقع خطا از PSFS_ERR_FATAL استفاده کنید تا pipeline متوقف شود و منابع آزاد شوند.
- قبل از استفاده در محیط تولید، تست با دادههای واقعی (اندازهها و الگوهای متفاوت) را فراموش نکنید.
نتیجهگیری
تابع stream_filter_prepend() ابزار قدرتمندی برای کنترل ترتیب اجرای فیلترها در streamهای PHP است. با ترکیب فیلترهای داخلی و فیلترهای کاربر میتوانید پردازشهای متنوعی مانند رمزنگاری، فشردهسازی، تبدیل متن و لاگگیری را بهسادگی انجام دهید. توجه به ترتیب، مدیریت بافرها و انتخاب بین prepend و append برای دستیابی به رفتار مطلوب ضروری است.
آیا این مطلب برای شما مفید بود ؟



