ویژگی تصویر

تابع strcmp() در PHP

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

تابع strcmp() یکی از توابع پایه‌ای برای مقایسه دو رشته در PHP است. این تابع دو رشته را به‌صورت باینری و حساس به حروف (case-sensitive) مقایسه می‌کند و بر اساس ترتیب بایت‌ها مقدار عددی برمی‌گرداند. در این مقاله به صورت جامع عملکرد، مقادیر بازگشتی، مثال‌های کاربردی، نکات امنیتی و جایگزین‌های مناسب را بررسی می‌کنیم.

نحوهٔ عملکرد و مقدار بازگشتی

تابع strcmp($a, $b) یکی از سه حالت زیر را بازمی‌گرداند:

مقدار بازگشتیمعنی
< 0رشتهٔ اول (a) از رشتهٔ دوم (b) کوچکتر است (در مقایسهٔ باینری)
0دو رشته دقیقاً برابرند
> 0رشتهٔ اول از رشتهٔ دوم بزرگتر است

مقدار دقیق مثبت یا منفی اهمیت ندارد؛ تنها علامت آن تعیین‌کننده است. مقایسه بر اساس مقدار عددی بایت‌ها انجام می‌شود، نه ترتیب حروف در الفبا یا تنظیمات محلی (locale).

مثال‌های ساده

$a = "apple";
$b = "banana";

$result = strcmp($a, $b);

if ($result === 0) {
    echo "Equal";
} elseif ($result < 0) {
    echo "$a is less than $b";
} else {
    echo "$a is greater than $b";
}

در این مثال strcmp مقدار منفی برمی‌گرداند چون “apple” از نظر بایت‌ها قبل از “banana” قرار می‌گیرد. توجه کنید که از === برای بررسی برابری با صفر استفاده شده تا نوع نیز ثابت بماند.

کاربردها و مثال‌های واقعی

  • مرتب‌سازی لیست رشته‌ای با حفظ حساسیت حروف
  • مقایسهٔ مقادیر ورودی تا زمانی که encoding یکنواخت باشد
  • استفاده در الگوریتم‌هایی که نیاز به ترتیب باینری دارند (مثلاً پیاده‌سازی درخت‌های جستجو)
$items = ["zebra", "apple", "Banana"];
usort($items, 'strcmp');
print_r($items);

در این مثال usort با strcmp یک مرتب‌سازی حساس به حروف انجام می‌دهد، بنابراین “Banana” (با حرف بزرگ) ممکن است در ترتیب متفاوتی نسبت به “banana” قرار گیرد چرا که کد بایت حروف بزرگ و کوچک متفاوت است.

نکات مهم و هشدارها

  • حساس به حروف: strcmp بزرگ و کوچک بودن حروف را تشخیص می‌دهد. برای مقایسهٔ بدون حساسیت از strcasecmp استفاده کنید.
  • کدینگ و چندبایتی: strcmp بایت‌محور است و برای رشته‌های UTF-8 که شامل کاراکترهای چندبایتی‌اند ممکن است رفتار مورد انتظار را نداشته باشد. برای مقایسهٔ صحیح متون چندبایتی از mb_strcmp (کتابخانه‌های سفارشی) یا تبدیل مناسب encoding بهره ببرید.
  • حساس به NULL و کاراکترهای مخفی: حضور بایت صفر (NULL) در رشته‌ها می‌تواند مقایسه را تحت‌تأثیر قرار دهد.
  • تایپ‌جگلینگ: strcmp فقط رشته‌ها را مقایسه می‌کند؛ اما اگر آرگومان‌ها نوع دیگری داشته باشند PHP آن‌ها را تبدیل به رشته می‌کند که ممکن است رفتار غیرمنتظره‌ای ایجاد کند.
  • امنیت و timing attacks: strcmp یک مقایسهٔ «زودهنگام» (early exit) انجام می‌دهد و برای مقاصد رمزنگاری یا مقایسهٔ توکن‌های حساس پیشنهاد نمی‌شود. برای مقایسه‌های مقاوم در برابر حملات زمان‌بری از hash_equals استفاده کنید.

مقایسه با عملگر === و جایگزین‌ها

برای بررسی برابری دقیق اغلب بهتر است از === استفاده کنید، چرا که علاوه بر مقدار، نوع را نیز بررسی می‌کند و برای بررسی دقیق تساوی رشته‌ای سریع‌تر و ساده‌تر است:

$a = "123";
$b = "123";

if ($a === $b) {
    // equal
}

اگر فقط می‌خواهید بدانید رشته‌ها برابرند، === از strcmp بهتر و خواناتر است. اما اگر نیاز به دانستن ترتیب (کمتر/بزرگتر) دارید، strcmp مناسب است.

جایگزین‌ها:

  • strcasecmp — مقایسهٔ بدون حساسیت به حروف
  • strncmp — مقایسهٔ n بایت اول
  • substr_compare — مقایسهٔ بخشی از رشته
  • hash_equals — مقایسهٔ مقاوم در برابر حملهٔ زمان‌بری (برای توکن‌ها و هش‌ها)

مثال: چرا hash_equals برای توکن‌ها بهتر است

$tokenFromUser = $_POST['token'] ?? '';
$expectedToken = 'abc123def456';

if (hash_equals($expectedToken, $tokenFromUser)) {
    // secure match
} else {
    // not match
}

در این مثال از hash_equals استفاده شده چون این تابع زمان اجرای ثابتی دارد و برای مقایسهٔ مقادیر حساس (مثل توکن CSRF یا هش پسورد) مناسب‌تر است. strcmp می‌تواند زمان اجرای متفاوتی برای رشته‌های متفاوت داشته باشد و در برابر حملات مبتنی بر زمان آسیب‌پذیر باشد.

مثال بهینه‌سازی: وقتی فقط برابری لازم است

// نه چندان بهینه
if (strcmp($a, $b) === 0) {
    // equal
}

// بهینه‌تر و خواناتر
if ($a === $b) {
    // equal
}

در اغلب شرایط، بررسی مستقیم با === ساده‌تر و سریع‌تر است. strcmp برای زمانی مناسب است که به ترتیب بین رشته‌ها نیاز دارید یا زمانی که می‌خواهید تفاوت lexicographic را بدانید.

خلاصهٔ نکات عملی

  • از strcmp برای مقایسهٔ حساس به حروف و بایت‌محور استفاده کنید.
  • برای مقایسهٔ بدون حساسیت به حروف از strcasecmp بهره ببرید.
  • برای مقایسهٔ امن توکن‌ها و هش‌ها از hash_equals استفاده کنید.
  • برای رشته‌های UTF-8 یا چندبایتی احتیاط کنید و در صورت نیاز از توابع mb_* یا تبدیل encoding استفاده کنید.
  • برای بررسی سادهٔ برابری، === اغلب خواناتر و سریع‌تر است.

با درک دقیق عملکرد strcmp و محدودیت‌های آن می‌توانید در کد PHP خود انتخاب مناسبی داشته باشید و از خطاها و مشکلات امنیتی جلوگیری کنید.

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

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