عوامل المقارنة في PHP

من موسوعة حسوب
< PHP
مراجعة 15:33، 6 يونيو 2018 بواسطة رؤيا-بنعطية (نقاش | مساهمات) (تعديلات طفيفة)
(فرق) → مراجعة أقدم | المراجعة الحالية (فرق) | مراجعة أحدث ← (فرق)

تتيح عوامل المقارنة -كما هو واضح من اسمها- مقارنة قيمتين مختلفتين. يمكنك أيضًا الاطلاع على جداول مقارنة الأنواع حيث ستجد العديد من الأمثلة المرتبطة بإجراء المقارنات بين الأنواع.

مثال الاسم النتيجة
‎$a == $b يساوي TRUE إن كان المتغير ‎$a مساويًا للمتغير ‎$b بعد تعديل الأنواع.
‎$a === $b مطابق TRUE إن كان ‎$a مساويًا للمتغير ‎$b، وكانا من النوع نفسه.
‎$a != $b لا يساوي TRUE إن كان ‎$a غير مساوٍ للمتغير ‎$b بعد تعديل الأنواع.
‎$a <> $b لا يساوي TRUE إن كان ‎ $aغير مساوٍ للمتغير ‎ $bبعد تعديل الأنواع.
‎$a !== $b لا يطابق TRUE إن كان ‎$a غير مساوٍ للمتغير ‎$b أو لم يكونا من النوع نفسه.
‎$a < $b أقل من TRUE إن كان ‎$a أقل من ‎$b.
‎$a > $b أكبر من TRUE إن كان ‎$a أكبر من ‎$b.
‎$a <= $b أقل من أو يساوي TRUE إن كان ‎$a أصغر من أو يساوي ‎$b.
‎$a >= $b أكبر من أو يساوي TRUE إن كان ‎$a أكبر من أو يساوي ‎$b.
‎$a <=> $b السفينة الفضائية Spaceship عدد صحيح يكون أصغر من أو يساوي أو أكبر من الصفر عندما يكون ‎$a أصغر من، أو يساوي أو أكبر من ‎$b. متوفر في PHP 7.

إن أجريت المقارنة بين عدد وسلسلة نصية أو إن تضمنت المقارنة أرقامًا في سلاسل نصية، فإن هذه السلاسل ستتحوّل إلى أعداد ثم تصبح المقارنة عددية. تنطبق هذه القاعدة على التعبير switch. لا تحدث عملية التحويل عند استخدام العامل === أو ‎!==‎ لإجراء المقارنة، إذ تجري المقارنة هنا بين القيمة والنوع.

<?php
var_dump(0 == "a"); // 0 == 0 -> true
var_dump("1" == "01"); // 1 == 1 -> true
var_dump("10" == "1e1"); // 10 == 10 -> true
var_dump(100 == "1e2"); // 100 == 100 -> true

switch ("a") {
case 0:
    echo "0";
    break;
case "a": 
// لا يمكن الوصول إلى هنا لأن "a" مطابقة أصلًا لـ 0
    echo "a";
    break;
}
?>
<?php  
// أعداد صحيحة
echo 1 <=> 1; // 0
echo 1 <=> 2; // -1
echo 2 <=> 1; // 1
 
// أعداد عشرية
echo 1.5 <=> 1.5; // 0
echo 1.5 <=> 2.5; // -1
echo 2.5 <=> 1.5; // 1
 
// سلاسل نصية
echo "a" <=> "a"; // 0
echo "a" <=> "b"; // -1
echo "b" <=> "a"; // 1
 
echo "a" <=> "aa"; // -1
echo "zz" <=> "aa"; // 1
 
// مصفوفات
echo [] <=> []; // 0
echo [1, 2, 3] <=> [1, 2, 3]; // 0
echo [1, 2, 3] <=> []; // 1
echo [1, 2, 3] <=> [1, 2, 1]; // 1
echo [1, 2, 3] <=> [1, 2, 4]; // -1
 
// كائنات
$a = (object) ["a" => "b"]; 
$b = (object) ["a" => "b"]; 
echo $a <=> $b; // 0
 
$a = (object) ["a" => "b"]; 
$b = (object) ["a" => "c"]; 
echo $a <=> $b; // -1
 
$a = (object) ["a" => "c"]; 
$b = (object) ["a" => "b"]; 
echo $a <=> $b; // 1
 
// مقارنة القيم فقط
$a = (object) ["a" => "b"]; 
$b = (object) ["b" => "b"]; 
echo $a <=> $b; // 1

?>

تتبع عملية المقارنة بين عدد من الأنواع التسلسل المعروض في الجدول التالي المقارنة مع أنواع مختلفة.

نوع المعامل الأول نوع المعامل الثاني النتيجة
null أو سلسلة نصية سلسلة نصية تحويل NULL إلى ""، مقارنة مفرداتية أو رقمية.
Bool أو null أي شيء تحويل كلا الجانبين إلى bool، ويكون FALSE < TRUE.
كائن كائن يمكن للأصناف المضمنة تعريف طريقتها الخاصة في المقارنة، الأصناف المختلفة غير قابلة للمقارنة، الأصناف المتشابهة تقارن الخصائص بنفس الطريقة المتبعة في المصفوفات (PHP 4)، في PHP 5 هناك توضيح خاص.
سلسلة نصية، أو مورد، أو عدد سلسلة نصية، أو مورد، أو عدد تحويل السلاسل النصية والموارد إلى أعداد، رياضيات اعتيادية.
مصفوفة مصفوفة المصفوفات ذات العناصر الأقل تكون أصغر، إن لم يتم العثور على المعامل 1 في المعامل 2 تصبح المصفوفات غير قابلة للمقارنة، وإلا تكون المقارنة قيمة بقيمة (انظر المثال التالي).
كائن أي شيء الكائن أكبر دائمًا.
مصفوفة أي شيء المصفوفة أكبر دائمًا.

المثال 1: مقارنة Boolean/null

<?php
// Bool و null
// تقارنان كقيم منطقية دائمًا

var_dump(1 == TRUE);
// TRUE
// ‎(bool)1‎ == TRUE‎‎ مثل
var_dump(0 == FALSE);
// TRUE
// ‎(bool)0 == FALSE‎‎ مثل

var_dump(100 < TRUE);
// TRUE
// ‎(bool)0 == FALSE‎‎ مثل

var_dump(-10 < FALSE);

// FALSE
// ‎(bool)-10 < FALSE‎‎ مثل

var_dump(min(-100, -10, NULL, 10, 100));

 // NULL - (bool)NULL < (bool)-100 هي FALSE < TRUE
?>

المثال 2: مقارنة المصفوفات

<?php
// تجري المقارنة في المصفوفات بهذه الطريقة باستخدام عوامل المقارنة الاعتيادية

function standard_array_compare($op1, $op2)
{
    if (count($op1) < count($op2)) {
        return -1; // $op1 < $op2
    } elseif (count($op1) > count($op2)) {
        return 1; // $op1 > $op2
    }
    foreach ($op1 as $key => $val) {
        if (!array_key_exists($key, $op2)) {
            return null; // uncomparable
        } elseif ($val < $op2[$key]) {
            return -1;
        } elseif ($val > $op2[$key]) {
            return 1;
        }
    }
    return 0; // $op1 == $op2
}
?>

انظر أيضًا: strcasecmp()‎ و strcmp()‎، وعوامل المصفوفات، وفصل الأنواع في هذا الدليل.

مقارنة الأعداد العشرية

لا تختبر المساواة بين عددين عشريين، وذلك بسبب الطريقة التي تمثّل من خلالها الأعداد العشرية داخليًا. راجع التوثيق الخاص بنوع البيانات float للمزيد من المعلومات.

العامل الثلاثي

هناك عامل شرطي آخر وهو العامل الثلاثي "‎?:‎".

المثال 3: إسناد قيمة افتراضية

<?php
// مثال على استخدام العامل الثلاثي

$action = (empty($_POST['action'])) ? 'default' : $_POST['action'];

// الشيفرة السابقة مطابقة لما يلي
if (empty($_POST['action'])) {
    $action = 'default';
} else {
    $action = $_POST['action'];
}

?>

يعيد التعبير (expr1) ? (expr2) : (expr3) التعبير expr2 إن كان expr1 صحيحًا TRUE، والتعبير expr3 إن expr1 خطأً FALSE.

ومنذ الإصدار 5.3 من PHP، أصبح بالإمكان التخلي عن التعبير الأوسط في العامل الثلاثي، فالتعبير expr1 ?: expr3 يعيد التعبير expr1 إن كان expr1 صحيحًا، وإلا فإنه سيعيد التعبير expr3.

ملاحظة: العامل الثلاثي هو تعبير (expression) ولا تُحسّب قيمته (evaluate) إلى متغيرٍ (variable)، بل إلى نتيجة لتعبير، وهو أمر يجب الانتباه إليه عند إرجاع المتغيرات بالمرجعية (return by reference). فالعبارة ‎‎return $var == 42 ? $a : $b;‎ لن تعمل في حال إرجاع المتغير بالمرجعية وستتلقّى تحذيرًا عند تنفيذها.

ملاحظة: ينصح بتجنب "تكديس" التعابير الثلاثية، إذ تسلك PHP سلوكًا غير واضح عند استخدام أكثر من عامل ثلاثي في عبارة واحدة.

المثال 4: السلوك غير الواضح للعامل الثلاثي

<?php
// نتيجة الشيفرة التالية غير واضحة
echo (true?'true':false?'t':'f');

// أصبحت الشيفرة أكثر وضوحًا
echo ((true ? 'true' : false) ? 't' : 'f');

?>

في المثال السابق سيبدو لك في الوهلة الأولى أن ناتج السطر الأول من الشيفرة هو 'true' ولكن النتيجة الحقيقية هي 't'، والسبب هو أن التعابير الثلاثية تعالج من اليسار إلى اليمين. لاحظ أن الشيفرة قد أصبحت أكثر وضوحًا في السطر الثاني، حيث أصبح من الواضح أن التعبير الأول يعيد 'true' والذي يعيد بدوره bool(true)‎‎ وهكذا يعاد الجزء الصحيح من التعبير الثلاثي.

عامل تجميع Null

يقدّم الإصدار 7 من PHP المعامل "??" أو عامل تجميع null (أي null coalescing).

المثال 5: إسناد قيمة افتراضية

<?php
// مثال على استخدام معامل تجميع null

$action = $_POST['action'] ?? 'default';

// الشيفرة السابقة مطابقة تمامًا لما يلي
if (isset($_POST['action'])) {
    $action = $_POST['action'];
} else {
    $action = 'default';
}

?>

يعيد التعبير (expr1) ?? (expr2) التعبير expr2 إن كانت قيمة expr1 هي NULL، ويعيد expr1 فيما عدا ذلك. لا يطلق هذا العامل أي تنويه (notice) في حال عدم وجود أي قيمة في الجهة اليسرى، كما هو الحال عند استخدام isset()‎. وهذا مفيد خصوصًا عند التعامل مع مفاتيح المصفوفات.

ملاحظة: عامل تجميع null هو تعبير لا يعيد متغيرًا، بل نتيجة لتعبير، وهو أمر يجب الانتباه إليه عند إرجاع المتغيرات بالمرجعية. فالعبارة ‎$foo ?? $bar لن تعمل في حال إرجاع المتغير بالمرجعية وستتلقّى تحذيرًا عند تنفيذها.

ملاحظة: يسمح عامل تجميع null بالتداخل البسيط.

المثال 6: مثال عن التداخل في عامل تجميع null

<?php

$foo = null;
$bar = null;
$baz = 1;
$qux = 2;

echo $foo ?? $bar ?? $baz ?? $qux; // النتيجة 1

?>

مصادر