Share This
//Variable Comparison in PHP

Variable Comparison in PHP

Bạn có thể code PHP, có thể sử dụng Framework này, Framework kia, nhưng liệu bạn đã thực sự hiểu hết về
meta của nó, bạn có thực sự nắm rõ được tính falsy và truthy, hay những phép so sánh của PHP.

Bạn có thực sự hiểu rõ PHP ?

Bạn có thể trả lời tất cả các câu hỏi bên dưới ?

Các phép toán dưới đây trả về true hay false?

** Chú ý: Phiên bản PHP được sử dụng là phiên bản PHP 5.6 nhé **

false == false // It will return true. Too easy, right ? :D

// But how about the following ? TRUE or FALSE ?
// Các phép so sánh sau trả về true hay false
1 == "1"
0 == "0"
"0" == "-0"
0 == false
"0" == false
"-0" == false
"0.0" == false
10 == "10tran duc thang 10"
"thang" == 0
"thang" == "0"
[] == false
null == []
null == ""
null == 0
null < -1
[] == 0
[] == ""
1 == "1 "
"1" == "1 "
"10" == "                    10"
"100" == "1e2"
"1000"  == "0x3e8"
"345" == "0345"
345 == 0345
"345" < "0346"
[1] == 1
(int) [1] == 1
(int) [0] == 0
false < -INF
false < NAN
true < INF
[1] == [1]
[1, 2] == [1 => 2, 0 => 1]
[1, 2] === [1 => 2, 0 => 1]
[1, 2] > 3
[1, 2] > "[1, 2]"
[1, 2] > [3]
[1, 2] > [2, 1]
(object) [1] > [1]

Nếu bạn có thể trả lời đúng hết, và hiểu được bản chất tại sao nó lại như vậy thì có lẽ bạn cũng đã nắm rõ hết được những gì mà bài viết này đề sẽ cập đến rồi. Còn ngược lại, hãy dành chút thời gian để đọc và tìm hiểu về những điều sẽ được giới thiệu dưới đây, bạn sẽ tự tìm được lời giải thích cho từng đáp án.

Variable Types

Để trả lời được những câu hỏi trên thì trước hết ta cần phải tìm hiểu và nắm rõ được về những kiểu giá trị có trong PHP.

Các kiểu giá trị trong PHP

  • String
  • Integer (Hay Long)
  • Float (Hay Double)
  • Boolean
  • Array
  • Object
  • NULL
  • Resource

Một số điều cần lưu ý

  • Kiểu Boolean gồm 2 giá trị là true và false
  • Kiểu Null chỉ gồm duy nhất một giá trị là null

Cũng giống như Javascript hay nhiều ngôn ngữ lập trình khác, để so sánh “bằng” trong PHP, ta có thể dùng == và ===

=== Strict Comparison hay Strict Equal, sẽ so sánh cả kiểu giá trị của 2 bên. Nếu 2 bên có kiểu giá trị khác nhau thì phép toán sẽ trả về giá trị false Phép toán === là rất minh bạch và dễ sử dụng, ít gây hiểu nhầm hay khó khăn gì cho lập trình viên.

Còn phép so sánh == Loose Comparison hay Loose Equal, thì sẽ tìm cách đưa 2 bên về cùng một kiểu giá trị rồi thực hiện phép so sánh.

Ta có thể dùng phép ép kiểu giống với C để đưa một biến từ kiểu giá trị này thành kiểu giá trị khác:

(boolean) 1 // true
(string) 10 // "10"
(int) "100" // 100
(int)[1] // 1

Những giá trị được coi là false

Đó là những giá trị khi được ép về kiểu Boolean sẽ cho giá trị là false Bao gồm:

  • false
  • 0
  • 0.0
  • "" (Xâu rỗng)
  • "0"
  • [] (Mảng không có phần tử)
  • null (Gồm cả những biến không được set giá trị)
  • SimpleXML objects (Được tạo từ tag rỗng)

Ví dụ

0.0 == false; // true
"0" == false; // true
$a = new SimpleXML('<div></div>');
$a == false; // true

Ngoài những giá trị là false kể trên, thì tất cả các giá trị khác đều được coi là true

So sánh trong PHP

Trong phần này, chúng ta sẽ tìm hiểu về một số trường hợp, hay quy tắc đặc biệt khi thực hiện các phép so sánh ==hay < >trong PHP.
Một số trong đó có thể gây bất ngờ cho bạn đấy. 😀

Null vs String

  • null được convert về xâu rỗng.
null == ""; // true
null == "0"; // false

Boolean & Null

  • Các biến khi so sánh với boolean hay null thì sẽ được ép về kiểu boolean Và khi so sánh 2 giá trị kiểu boolean với nhau thì false < true
NAN == true; // true
null < NAN; // true
"0" < true; // true

String vs String

  • Phép so sánh String với String sử dụng ==trông qua thì có vẻ đơn giản, bởi 2 bên đã cùng một loại rồi, ta chỉ cần xem giá trị của nó có giống nhau hay không mà thôi. Thế nhưng mọi thứ lại không hẳn như vậy, đôi khi so sánh 2 String thì chúng lại bị ép về kiểu… Integer hay Float =)).
  • Chẳng hạn như phép so sánh "1" == "1.0" trả về… truemặc dù 2 chuỗi đó là khác nhau (wtf, (facepalm)).
  • Thậm chí một String có chữ ehay 0xcũng có thể bị ép về kiểu số nếu có thể (facepalm).
"100" == "10e1"; // true
"16"  == "0x10"; // true
  • Hơn thế nữa, nếu trong một chuỗi là một số và có space hay tab ở đằng trước, thì chúng sẽ bị loại bỏ.
"1" == " 1"; // true
"2"  == " \t\n 2"; // true
"   3" == "\t 3"; // true
  • Tuy nhiên, nếu có space, tab,… hay bất kỳ ký tự nào ở đằng sau thì chúng sẽ không bị ép về giá trị number để so sánh nữa :v.
"1" == "1 "; // false
"2" == "2a"; // false
"3 " == "3  "; // false
  • Phép so sánh String với String sử dụng == thật sự rất nguy hiểm và đem lại nhiều kết quả không mong muốn, thế nên đừng sử dụng nó khi mà bạn không biết chắc là mình đang làm gì nhé =))

Number vs String

  • String sẽ được ép về giá trị number (Integer hoặc Float).
  • Nếu một string bắt đầu bằng một số thì nó sẽ có giá trị là số đó.
  • Nếu một string không bắt đầu bằng một số thì nó sẽ có giá trị là 0
0 == "thang"; // true
345 == "345 thang"; // true
100 == "10e1thang"; // true

Array vs Array

  • Hai array là “bằng nhau” theo phép so sánh == nếu chúng có các cặp key và value là “bằng nhau”. Việc so sánh key, value cũng được thực hiện bằng phép so sánh == Thứ tự của các cặp key, value trong array không gây ra ảnh hưởng gì.
$array1 = ['3' => 3, '2' => 2, '1' => 1, '0' => 0];
$array2 = [false => '0', 1 => '1', 2 => '2', 3 => '3'];
$array1 == $array2; // true
$array1 === $array2; // false
  • Hai array là “bằng nhau” theo phép so sánh ===nếu chúng có các cặp key và value là “bằng nhau”. Việc so sánh key, value cũng được thực hiện bằng phép so sánh ===Thứ tự của các cặp key, value trong array khác nhau sẽ khiến các array được coi là khác nhau.
$array1 = [0, 1, 3];
$array2 = [0, 2 => 3, 1 => 1];
$array3 = [0, 1 => 1, 2 => 3];
$array1 == $array2; // true
$array1 == $array3; // true
$array1 === $array2; // false
$array1 === $array3; // true
  • Khi so sánh 2 array bằng phép toán > hay <thì array nào có nhiều phần tử hơn thì sẽ lớn hơn. Nếu 2 array cùng số phần tử, và các key giống nhau thì sẽ so sánh lần lượt các phần tử với nhau. (Nếu các key khác nhau thì sẽ không so sánh được, phép toán sẽ trả về false
[1, 2] > [100000]; // true
[1, 3] > [1, 2]; // true
[1, 2] > [3 => 3]; // true
[1 => 1] > [0 => 0]; // false

Object vs Object

  • Các instance của các Class khác nhau thì không so sánh được.
  • Các object “bằng nhau” theo phép toán ==nếu chúng là instances của cùng một Class, và có cùng các attributes và giá trị các attributes cũng “bằng nhau”;
  • Các object “bằng nhau” theo phép toán ===nếu và chỉ nếu chúng cùng trỏ đến một instance.
class C
{
    public $c;
    public function __construct($c)
    {
        $this->c = $c;
    }
}
$a = new C("1");
$b = new C(1);
$a == $b; // true
$a === $b; // false
$a = $b = new C(1);
$a === $b; // true

Other

  • Một array sẽ lớn hơn > mọi giá trị khác mà không phải là boolean, array hay object. Tức phép toán so sánh > giữa array và vế kia là integer, float, string, null,… thì đều trả về truetrừ việc [] == null trả về truevà do đó [] > nulltrả về false
  • Array có thể ép về kiểu number, trong đó array rỗng thì cho giá trị 0ngoài ra cho giá trị 1
  • Một object sẽ lớn hơn > một array.
[0] > 100; // true
[1] > "thang"; // true
(int) [null] == 1; // true
(float) [] == 0; // true
new stdClass > [1]; // true

Fun fact

  • Phép toán == trong PHP không có tính phản thân (reflexive), tức $a == $a không phải lúc nào cũng đúng =)). Ví dụ: NAN == NAN sẽ trả về false
  • Phép toán == trong PHP có tính đối xứng (symmetric), tức $a == $b và $b == $a sẽ trả về cùng một kết quả.
  • Phép toán == trong PHP không có tính chất bắc cầu (transitive), tức $a == $b và $b == $c trả về truenhưng $a == $c chưa chắc đã trả về true.
    Ví dụ:
1 == true; // true
2 == true; // true
1 == 2; // false
  • Phép toán <=hay >=trong PHP không có tính phản xứng (anti-symmetric), tức $a <= $b và $b <= $ađều trả về true nhưng chưa chắc $a == $b đã trả về true
NAN <= "thang"; // bool(true)
"thang" <= NAN; // bool(true)
NAN == "thang"; // bool(false)
  • Phép toán <=hay < đều không có tính chất bắc cầu (transitive)
  • Phép toán <=hay < đều không có tính toàn bộ (total), tức cả $a <= $b và $b <= $a đều có thể trả về falsehay cả $a < $b $b < $a và $a == $b cũng thế.
NAN <= 0; // false
0 <= NAN; // false
[0 => 1] > [1 => 0]; // false
[0 => 1] < [1 => 0]; // false
[0 => 1] == [1 => 0]; // false
  • Trong version 7, PHP có giới thiệu một phép toán mới, đó là <=>Phép so sánh $a <=> $b sẽ trả về -1 nếu $a < $btrả về 0 nếu $a == $b và trả về 1 nếu $a > $b
  • Chắc hẳn bạn đã từng sử dụng Ternary Operation, toán tử 3 ngôi:
$x = $a ? $b : $c;

Phép toán $x = $a ? $a : $b; có thể được viết ngắn lại thành $x = $a ?: $b;

  • Cũng liên quan đến Ternary Operation, theo bạn phép toán sau trả về kết quả gì ?
true ? false : true ? false : true;

Mới nhìn qua, có thể bạn sẽ trả lời kết quả là falsevới thứ tự thực hiện phép toán là true ? (false) : (true ? false : true)tuy nhiên thứ tự đúng sẽ phải là (true ? false : true) ? false : truevà do đó, phép toán sẽ trả về true

Kết quả

Dưới đây là đáp án cho những câu hỏi được đưa ra ở đầu bài viết.

Nếu bạn đã đọc hết phần phía trên rồi thì chắc có thể hiểu được tại sao nó lại ra được đáp án như dưới đây. Còn nếu có câu nào mà bạn vẫn chưa hiểu được nguyên nhân thì điều đó có nghĩa là bạn đã bỏ sót điều gì đó rồi đấy, kéo lên đọc lại thôi (honho)

Nếu có thắc mắc gì hãy để lại tin nhắn ở phần comment nhé.

false == false // It will return true. Too easy, right ? :D

// But how about the following ? TRUE or FALSE ?
// Các phép so sánh sau trả về true hay false
1 == "1"; // true
0 == "0"; // true
"0" == "-0"; // true
0 == false; // true
"0" == false; // true
"-0" == false; // false
"0.0" == false; // false
10 == "10tran duc thang 10"; // true
"thang" == 0; // true
"thang" == "0"; // false
[] == false; // true
null == []; // true
null == ""; // true
null == 0; // true
null < -1; // true
[] == 0; // false
[] == ""; // false
1 == "1 "; // true
"1" == "1 "; // false
"10" == "                    10"; // true
"100" == "1e2"; // true
"1000"  == "0x3e8"; // true
"345" == "0345"; // true
345 == 0345; // false
"345" < "0346"; // true
[1] == 1; // false
(int) [1] == 1; // true
(int) [0] == 0; // false
false < -INF; // true
false < NAN; // true
true < INF; // false
[1] == [1]; // true
[1, 2] == [1 => 2, 0 => 1]; // true
[1, 2] === [1 => 2, 0 => 1]; // false
[1, 2] > 3; // true
[1, 2] > "[1, 2]"; // true
[1, 2] > [3]; // true
[1, 2] > [2, 1]; // false
(object) [1] > [1]; // true

Bài viết chắc vẫn chưa thể cover hết được những vấn đề trong các phép toán so sánh trong PHP. Ngoài ra nhiều chỗ mình cũng viết dựa trên kinh nghiệm và những gì mình biết. Có thể còn có nhiều chỗ thiếu sót, hy vọng nhận được ý kiến đóng góp của các bạn.

Nguồn: viblo.asia.


ỨNG TUYỂN







    Chế độ phúc lợi

    CHÍNH SÁCH LƯƠNG & THƯỞNG

    Thấu hiểu tâm tư nguyện vọng của nhân viên, công ty Rivercrane Việt Nam đặc biệt thiết lập chế độ xét tăng lương định kỳ 2lần/năm. Xét đánh giá vào tháng 06 và tháng 12 hàng năm và thay đổi lương vào tháng 01 và tháng 07 hàng năm. Ngoài ra, nhân viên còn được thưởng thành tích định kỳ cho các cá nhân xuất sắc trong tháng, năm.

    CHẾ ĐỘ ĐÀO TẠO TẠI NHẬT

    Luôn luôn mong muốn các kỹ sư và nhân viên trong công ty có cái nhìn toàn diện về lập trình những mảng kỹ thuật trên thế giới, công ty Rivercrane Việt Nam quyết định chế độ 3 tháng 1 lần đưa nhân viên đi học tập tại Nhật. Các bạn kỹ sư hoàn toàn đều có thể quyết định khả năng phát triển bản thân theo hướng kỹ thuật hoặc theo hướng quản lý.

    CHẾ ĐỘ ĐI DU LỊCH HÀNG NĂM

    Không chỉ đưa đến cho nhân viên những công việc thử thách thể hiện bản thân, công ty Rivercrane Việt Nam muốn nhân viên luôn thích thú khi đến với những chuyến hành trình thú vị hàng năm. Những buổi tiệc Gala Dinner sôi động cùng với những trò chơi Team Building vui nhộn sẽ giúp cho đại gia đình Rivercrane thân thiết hơn.

    CHẾ ĐỘ EVENT CÔNG TY

    Những hoạt động Team building, Company Building, Family Building, Summer Holiday, Mid-Autumn Festival… sẽ là những khoảnh khắc gắn kết đáng nhớ của mỗi một nhân viên trong từng dự án, hoặc sẽ là những điều tự hào khi giới thiệu công ty mình với với gia đình thân thương, cùng nhau chia sẻ yêu thương với thông điệp “We are One”

    BẢO HIỂM

    Công ty Rivercrane Việt Nam đảm bảo tham gia đầy đủ chế độ Bảo hiểm xã hội, bảo hiểm y tế và bảo hiểm thất nghiệp. Cam kết chặt chẽ về mọi thủ tục phát sinh công ty đều hỗ trợ và tiến hành cho nhân viên từ đầu đến cuối. Những chế độ bảo hiểm khác công ty cũng đặc biệt quan tâm và từng bước tiến hành.

    CHẾ ĐỘ PHÚC LỢI KHÁC

    Hỗ trợ kinh phí cho các hoạt động văn hóa, văn nghệ, thể thao; Hỗ trợ kinh phí cho việc mua sách nghiên cứu kỹ thuật; Hỗ trợ kinh phí thi cử bằng cấp kỹ sư, bằng cấp dành cho ngôn ngữ. Hỗ trợ kinh phí tham gia các lớp học về quản lý kỹ thuật bên ngoài; Các hỗ trợ phúc lợi khác theo quy định công ty…

    CÔNG VIỆC TƯƠNG TỰ

    © 2012 RiverCrane Vietnam. All rights reserved.

    Close