ویژگی تصویر

تابع preg_quote() در PHP

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

تابع preg_quote() یکی از ابزارهای ساده ولی حیاتی در هنگام کار با الگوهای منظم (PCRE) در PHP است. این تابع رشته‌ای را می‌گیرد و تمام کاراکترهای معنادار برای یک الگوی منظم را با بک‌اسلش فرار (escape) می‌کند، به طوری که آن رشته دیگر به‌عنوان الگو تفسیر نشود بلکه به‌صورت متن ساده در نظر گرفته شود.

چرا به preg_quote نیاز داریم؟

  • وقتی رشته‌ای از ورودی کاربر داخل یک الگوی regex قرار می‌گیرد، ممکن است شامل کاراکترهای ویژه‌ای باشد که معنای نگارش (metacharacters) دارند؛ این باعث ایجاد خطا یا رفتار ناخواسته می‌شود.
  • preg_quote از بروز “regex injection” جلوگیری می‌کند، یعنی کاربر نمی‌تواند با ارسال کاراکترهای خاص، منطق الگو را تغییر دهد.
  • استفاده از preg_quote ساده‌ترین راه برای جستجوی دقیق (literal search) وقتی از توابع preg_* استفاده می‌کنیم است.

نحوه‌ی کار و پارامترها

تابع به شکل زیر فراخوانی می‌شود:

string preg_quote ( string $str , ?string $delimiter = null )

پارامترها:

  • $str: رشته‌ای که باید فرار شود.
  • $delimiter (اختیاری): اگر از یک جداکننده (delimiter) خاص برای الگو استفاده می‌کنید (مثلا / یا #)، می‌توانید آن را تعیین کنید تا تابع آن جداکننده را هم escape کند.

کدام کاراکترها فرار می‌شوند؟

preg_quote معمولاً کاراکترهای زیر را با بک‌اسلش پیش از آن‌ها بازمی‌گرداند:

کاراکترها. + * ? [ ^ ] $ ( ) { } = ! < > | : –

همچنین اگر پارامتر delimiter تعیین شود، آن کاراکتر نیز escape می‌شود. این خصوصیت معمولاً برای جلوگیری از فرار دستی جداکننده مفید است.

مثال‌های عملی

1) جستجوی یک عبارت که ممکن است شامل اسلش (/) باشد:

$needle = '/path/to/file.php';
$pattern = '/' . preg_quote($needle, '/') . '/';
if (preg_match($pattern, $haystack)) {
    // found
}

توضیح: در این مثال ما از جداکنندهٔ پیش‌فرض “/” استفاده می‌کنیم، بنابراین preg_quote($needle, ‘/’) باعث می‌شود که همه کاراکترهای معنی‌دار و همچنین خود علامت “/” با بک‌اسلش فرار شوند. اگر پارامتر delimiter را مشخص نکنیم، اسلش در خروجی escape نخواهد شد و الگو خراب می‌شود.

2) جلوگیری از regex injection هنگام جستجوی عبارت وارد شده توسط کاربر:

$userInput = $_GET['q'] ?? '';
$pattern = '/b' . preg_quote($userInput, '/') . 'b/i';
if (preg_match($pattern, $text)) {
    echo 'Found';
}

توضیح: این الگو از b برای محدود کردن به کلمات کامل استفاده می‌کند و preg_quote تضمین می‌کند که هر کاراکتر خاصی در ورودی کاربر به عنوان متن عادی مورد بررسی قرار گیرد. همچنین مِدیفایر i برای حساس‌نبودن به حروف کوچک/بزرگ اضافه شده است.

مثال در جایگزینی با preg_replace

$search = '1+1=2';
$replace = '[matched]';
$pattern = '/' . preg_quote($search, '/') . '/';
$result = preg_replace($pattern, $replace, $subject);

توضیح: اگر بخواهید یک رشتهٔ دقیق را در متن جایگزین کنید و آن رشته ممکن است کاراکترهای regex داشته باشد، باید آن را با preg_quote فرار کنید. در غیر این صورت + یا سایر نشانه‌ها به‌عنوان اپراتور برای الگو تفسیر می‌شوند.

نکات و دام‌های رایج

  • فراموش نکنید که اگر از جداکنندهٔ پیش‌فرض (/) استفاده می‌کنید و رشته می‌تواند شامل / باشد، حتماً پارامتر delimiter را به preg_quote بدهید.
  • preg_quote فقط نقش فرار کردن کاراکترها را دارد؛ معنای منطقی الگوها (مانند گروه‌بندی، کلاس‌های کاراکتری) را تغییر نمی‌دهد. بنابراین اگر نیاز به پردازش پیچیده‌تر دارید، باید الگوی نهایی را دقیق‌تر بسازید.
  • اجتناب از فرار دوبل: نیازی نیست یک رشته را چندبار preg_quote کنید؛ این کار باعث اضافه شدن بک‌اسلش‌های بیشتر و ناهماهنگی می‌شود.
  • اگر قرار است رشته را داخل یک کلاس کاراکتری قرار دهید (مثلاً [ … ] )، preg_quote امن است اما معمولاً برخی کاراکترها داخل کلاس معنای متفاوتی دارند؛ با این حال preg_quote آنها را هم فراری می‌دهد و همین باعث می‌شود در اکثر موارد مشکلی پیش نیاید.
  • برای جستجوهای ساده و دقیق می‌توانید به‌جای preg_* از strpos یا str_contains (در PHP 8) استفاده کنید که سریع‌تر و ساده‌تر است؛ اما اگر نیاز به امکانات regex دارید، از preg_quote استفاده کنید.

بهینه‌سازی و بهترین روش‌ها

  • اگر فقط به دنبال بررسی وجود یک زیررشته هستید، از strpos/str_contains استفاده کنید تا از هزینهٔ پردازش regex جلوگیری کنید.
  • برای کارایی بهتر روی رشته‌های بزرگ در حلقه‌ها، مقدار فرار شده را یک‌بار بسازید و مجدداً از آن استفاده کنید.
  • همیشه مِدیفایرها (مانند i، u، m) را در نظر بگیرید؛ اگر از یونیکد استفاده می‌کنید، مِدیفایر u را اضافه کنید.

نمونهٔ کامل: تابع ایمن جستجو

function safePregSearch(string $needle, string $haystack): bool {
    // از اسلش به عنوان delimiter استفاده می‌کنیم و آن را نیز escape می‌کنیم
    $pattern = '/' . preg_quote($needle, '/') . '/u';
    return preg_match($pattern, $haystack) === 1;
}

توضیح: این تابع یک ورودی امن می‌سازد که برای جستجوی literal در متن مناسب است. از مِدیفایر u برای پشتیبانی از یونیکد استفاده شده و از preg_match === 1 برای چک نتایج معتبر بهره گرفته شده است.

خلاصه

preg_quote() ابزاری ساده اما بسیار مهم برای هر کسی است که با regular expressions در PHP کار می‌کند. این تابع باعث می‌شود تا ورودی‌های پویا و کاربر-محور به‌صورت ایمن در الگوهای regex به‌کار گرفته شوند، از خطاهای نحوی جلوگیری شود و خطرات تزریق الگوی منظم کاهش یابد. با درک پارامتر delimiter و توجه به مثال‌های بالا می‌توانید از آن به‌صورت موثر و ایمن در پروژه‌های خود استفاده کنید.

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

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