- ساخت فیلترهای سفارشی
در بخش سوم با استریم php://filter آشنا شدیم. همانطور که میدانید، این استریم امکان فیلتر کردن و پردازش دادههای ورودی یا خروجی را در حین خواندن و نوشتن فراهم میکند. همچنین با فیلترهایی مانند string.toupper و string.strip_tags آشنا شدیم.
در PHP، کلاس php_user_filter پایهای است برای تعریف فیلترهای استریم سفارشی (Custom Stream Filters). وقتی شما یک فیلتر سفارشی میسازید، باید از این کلاس ارثبری کنید و متدهای آن را پیادهسازی کنید تا بتوانید روی دادههای استریم، پردازش دلخواه خود را انجام دهید.
- ساختار کلی کلاس php_user_filter
1- متد filter
این متد مهمترین بخش فیلتر است. دادههای ورودی از استریم در قالب یک یا چند "باکت" (bucket) به این متد میآیند. هدف شما این است که دادهها را در هر باکت پردازش کنید و سپس آن را به باکتهای خروجی منتقل کنید.
public function filter(resource $in, resource $out, int &$consumed, bool $closing): int
{
//
}
پارامتر in : استریم ورودی که دادههای خام در قالب باکتها داخلش هستند.
پارامتر out : استریم خروجی که باید دادههای پردازش شده داخلش قرار بگیرد.
پارامتر consumed : تعداد بایتهایی که از ورودی خوانده و مصرف شدهاند. باید این مقدار را بهروز کنید.
پارامتر closing : اگر true باشد، استریم در حال بسته شدن است و باید پردازش نهایی انجام شود.
این متد باید یک عدد صحیح را return کند، این عدد بین 0 تا 2 می باشد که در قالب ثابت های زیر موجود هستند:
ثابت PSFS_PASS_ON : ادامه معمولی پردازش (عدد 0)
ثابت PSFS_FEED_ME : منتظر داده بیشتر باش (عدد 1)
ثابت PSFS_ERR_FATAL : خطای بحرانی (عدد 2)
در ادامه یک فیلتر برای بزرگ کردن حروف ایجاد می کنیم:
public function filter(resource $in, resource $out, int &$consumed, bool $closing): int
{
while ($bucket = stream_bucket_make_writeable($in)) {
$bucket->data = strtoupper($bucket->data);
$consumed += $bucket->datalen;
stream_bucket_append($out, $bucket);
}
return PSFS_PASS_ON;
}
در هر تکرار، تابع stream_bucket_make_writeable($in) یک "باکت" دادهای از ورودی دریافت میکند.
باکت یک ساختار است که شامل دادههای خام ($bucket->data) و طول دادهها ($bucket->datalen) است.
اگر دادهای وجود داشته باشد، باکت به صورت نوشتنی بازگردانده میشود.
در این مثال، دادههای موجود در باکت به حروف بزرگ تبدیل میشوند:
$bucket->data = strtoupper($bucket->data);
یعنی هر رشتهای که از ورودی آمده، با strtoupper تبدیل به حروف بزرگ میشود.
تعداد بایتهایی که از ورودی خوانده شده است باید به $consumed اضافه شود:
$consumed += $bucket->datalen;
این به PHP کمک میکند بفهمد چقدر از دادهها مصرف شدهاند.
پس از پردازش، باکت به استریم خروجی ارسال میشود:
stream_bucket_append($out, $bucket);
به این ترتیب، دادههای پردازش شده آماده خواندن در خروجی هستند.
در نهایت، مقدار PSFS_PASS_ON برگردانده میشود، این مقدار به معنی "ادامه پردازش عادی" است و نشان میدهد که فیلتر با موفقیت کار خود را انجام داده است.
———
2- متد onCreate
این متد هنگام ایجاد فیلتر و اتصال آن به استریم فراخوانی میشود.
public function onCreate(): bool
{
//
}
میتوانید در اینجا پارامترهای ورودی در $this->params را پردازش یا مقداردهی اولیه انجام دهید.
اگر مقدار true بازگردد، اجازه ساخت استریم داده می شود. در غیر این صورت ایجاد فیلتر به شکست میخورد.
———
3- متد onClose
زمانی که استریم بسته میشود، این متد فراخوانی میشود تا فیلتر بتواند منابع را آزاد کند یا تمیزکاری کند.
public function onClose(): void
{
//
}
نکته: تنها پیاده سازی متد filter اجباری می باشد.
- مثال کامل
class UppercaseFilter extends php_user_filter
{
public function filter($in, $out, &$consumed, $closing): int
{
while ($bucket = stream_bucket_make_writeable($in)) {
$bucket->data = strtoupper($bucket->data);
$consumed += $bucket->datalen;
stream_bucket_append($out, $bucket);
}
return PSFS_PASS_ON;
}
}
stream_filter_register('my_uppercase', 'UppercaseFilter') or die('Failed to register filter');
$fp = fopen('php://memory', 'r+');
fwrite($fp, "hello");
rewind($fp);
stream_filter_append($fp, 'my_uppercase');
echo stream_get_contents($fp); // HELLO
// OR
echo file_get_contents("php://filter/read=my_uppercase/resource=input.txt");
#PHP #PHP_streams
@AmirhDeveloper
.