So sánh tốc ký trong PHP

8 minute read

So sánh tốc ký trong PHP

Có thể bạn đã biết một số toán tử so sánh trong PHP. Những thứ như ternary ?:, the null coalescing ?? và the spaceship <=> . Nhưng bạn có thực sự biết chúng hoạt động như thế nào không? Việc hiểu các toán tử này giúp bạn sử dụng chúng nhiều hơn, dẫn đến codebase sạch hơn.

Trước khi tìm hiểu sâu về từng toán tử, đây là tóm tắt về những gì mỗi toán tử làm:

# Toán tử ternary

Toán tử ternary là cách viết tắt của cấu trúc if {} else {}. Thay vì viết thế này:

if ($condition) {
    $result = 'foo' 
} else {
    $result = 'bar'
}

Bạn có thể viết thế này:

$result = $condition ? 'foo' : 'bar';

Nếu giá trị $conditiontrue, thì toán hạng bên trái sẽ được gán cho $result. Nếu là false, thì toán hạng bên phải sẽ được sử dụng.

Thực tế thú vị: tên toán tử bậc ba thực sự có nghĩa là “một toán tử hoạt động trên ba toán hạng”. Một toán hạng là một thuật ngữ dùng để chỉ các bộ phận cần thiết của một biểu thức. Toán tử bậc ba là toán tử duy nhất trong PHP yêu cầu ba toán hạng: điều kiện, truefalsekết quả. Tương tự, cũng có các toán tử nhị phân và đơn phân. Bạn có thể đọc thêm về nó ở đây .

Quay lại toán tử bậc ba: bạn có biết biểu thức nào đánh giá và biểu thức truenào không? Hãy nhìn vào booleancột của bảng này .

Toán tử bậc ba sẽ sử dụng toán hạng bên trái của nó khi điều kiện đánh giá là true. Đây có thể là một chuỗi, một số nguyên, một boolean, v.v. Toán hạng bên phải sẽ được sử dụng cho cái gọi là “giá trị sai”.

Các ví dụ sẽ là 0hoặc '0', một mảng hoặc chuỗi trống null, một biến không xác định hoặc chưa được gán và tất nhiên là falsechính nó. Tất cả các giá trị này sẽ làm cho toán tử bậc ba sử dụng toán hạng bên phải của nó.

# Toán tử bậc ba viết tắt

Kể từ PHP 5.3, có thể bỏ đi toán hạng bên trái, cho phép các biểu thức thậm chí còn ngắn hơn:

$result = $initial ?: 'default';

Trong trường hợp này, giá trị của $resultsẽ là giá trị của $initial, trừ khi được $initialđánh giá là false, trong trường hợp đó chuỗi 'default'được sử dụng.

Bạn có thể viết biểu thức này theo cách tương tự bằng cách sử dụng toán tử bậc ba thông thường:

$result = $condition ? $condition : 'default';

Trớ trêu thay, bằng cách bỏ đi toán hạng thứ hai của toán tử bậc ba, nó thực sự trở thành một toán tử nhị phân .

# Chuỗi toán tử bậc ba

Sau đây, mặc dù nó có vẻ logic; không hoạt động trong PHP:

$result = $firstCondition
    ? 'truth'
    : $elseCondition
        ? 'elseTrue'
        : 'elseFalse';

Lý do là vì toán tử bậc ba trong PHP là phép liên kết trái và do đó được phân tích cú pháp theo một cách rất lạ. Ví dụ trên luôn đánh giá $elseConditionphần đầu tiên, vì vậy ngay cả khi $firstConditiontrue, bạn sẽ không bao giờ nhìn thấy đầu ra của nó.

Tôi tin rằng điều đúng đắn cần làm là tránh tất cả các toán tử bậc ba lồng nhau. Bạn có thể đọc thêm về hành vi kỳ lạ này trong câu trả lời Stack Overflow này .

Hơn nữa, như PHP 7.4, việc sử dụng các cụm từ có chuỗi không có dấu ngoặc sẽ không được dùng nữa .

# toán tử liên kết Null

Bạn đã xem qua bảng so sánh các loại trước đó chưa? Toán tử liên kết null có sẵn kể từ PHP 7.0. Nó tương tự như toán tử bậc ba, nhưng sẽ hoạt động giống như issettrên toán hạng bên trái thay vì chỉ sử dụng giá trị boolean của nó. Điều này làm cho toán tử này đặc biệt hữu ích cho mảng và gán giá trị mặc định khi một biến không được đặt.

$undefined ?? 'fallback'; // 'fallback'

$unassigned;
$unassigned ?? 'fallback'; // 'fallback'

$assigned = 'foo';
$assigned ?? 'fallback'; // 'foo'

'' ?? 'fallback'; // ''
'foo' ?? 'fallback'; // 'foo'
'0' ?? 'fallback'; // '0'
0 ?? 'fallback'; // 0
false ?? 'fallback'; // false

Toán tử kết hợp null nhận hai toán hạng, làm cho nó trở thành toán tử nhị phân . Nhân tiện, “kết hợp” có nghĩa là “kết hợp với nhau để tạo thành một khối hoặc toàn bộ”. Sẽ cần đến hai toán hạng và quyết định sử dụng toán hạng nào dựa trên giá trị của toán hạng bên trái.

# Null liên kết trên các mảng

Toán tử này đặc biệt hữu ích khi kết hợp với các mảng, vì nó hoạt động như thế nào isset. Điều này có nghĩa là bạn có thể nhanh chóng kiểm tra sự tồn tại của các khóa, thậm chí cả các khóa lồng nhau, mà không cần viết các biểu thức dài dòng.

$input = [
    'key' => 'key',
    'nested' => [
        'key' => true
    ]
];

$input['key'] ?? 'fallback'; // 'key'
$input['nested']['key'] ?? 'fallback'; // true
$input['undefined'] ?? 'fallback'; // 'fallback'
$input['nested']['undefined'] ?? 'fallback'; // 'fallback'

null ?? 'fallback'; // 'fallback'

Ví dụ đầu tiên cũng có thể được viết bằng toán tử bậc ba:

$output = isset($input['key']) ? $input['key'] : 'fallback';

Lưu ý rằng không thể sử dụng toán tử bậc ba viết tắt khi kiểm tra sự tồn tại của các khóa mảng. Nó sẽ kích hoạt lỗi hoặc trả về boolean, thay vì giá trị của toán hạng bên trái thực.

// Returns `true` instead of the value of `$input['key']`
$output = isset($input['key']) ?: 'fallback' 

// The following will trigger an 'undefined index' notice 
// when $output is no array or has no 'key'.
//
// It will trigger an 'undefined variable' notice 
// when $output doesn't exist.
$output = $input['key'] ?: 'fallback';

# Null kết hợp chuỗi

Toán tử liên kết null có thể dễ dàng được xâu chuỗi:

$input = [
    'key' => 'key',
];

$input['undefined'] ?? $input['key'] ?? 'fallback'; // 'key'

# Liên kết lồng nhau

Có thể sử dụng toán tử liên kết null trên các thuộc tính đối tượng lồng nhau, ngay cả khi một thuộc tính trong chuỗi là null.

$a = (object) [
    'prop' => null,
];

var_dump($a->prop->b ?? 'empty');

// 'empty'

# Toán tử gán liên kết rỗng

Trong PHP 7,4, chúng ta có thể mong đợi một cú pháp thậm chí còn ngắn hơn được gọi là “toán tử gán liên kết null” .

// This operator will be available in PHP 7.4

function (array $parameters = []) {
    $parameters['property'] ??= 'default';
}

Trong ví dụ này, $parameters['property']sẽ được đặt thành 'default', trừ khi nó được đặt trong mảng được truyền cho hàm. Điều này sẽ tương đương với điều sau, sử dụng toán tử kết hợp null hiện tại:

function (array $parameters = []) {
    $parameters['property'] = $parameters['property'] ?? 'default';
}

# toán tử tàu vũ trụ

toán tử tàu vũ trụ, trong khi có một cái tên khá kỳ lạ, có thể rất hữu ích. Đó là một toán tử được sử dụng để so sánh. Nó sẽ luôn luôn trở lại một trong ba giá trị: 0, -1hoặc 1.

0sẽ được trả về khi cả hai toán hạng bằng nhau, 1khi toán hạng bên trái lớn hơn và -1khi toán hạng bên phải lớn hơn. Hãy xem một ví dụ đơn giản:

1 <=> 2; // Will return -1, as 2 is larger than 1.

Ví dụ đơn giản này không phải là tất cả những gì thoát, phải không? Tuy nhiên, toán tử tàu vũ trụ có thể so sánh nhiều hơn các giá trị đơn giản!

// It can compare strings,
'a' <=> 'z'; // -1

// and arrays,
[2, 1] <=> [2, 1]; // 0

// nested arrays,
[[1, 2], [2, 2]] <=> [[1, 2], [1, 2]]; // 1

// and even casing.
'Z' <=> 'z'; // -1

Thật kỳ lạ, khi so sánh cách viết hoa của chữ cái, chữ cái viết thường được coi là cao nhất. Có một lời giải thích đơn giản. So sánh chuỗi được thực hiện bằng cách so sánh từng ký tự. Ngay sau khi một ký tự khác nhau, giá trị ASCII của chúng sẽ được so sánh. Vì các chữ cái thường đứng sau các chữ cái viết hoa trong bảng ASCII nên chúng có giá trị cao hơn.

# So sánh các đối tượng

Người điều khiển tàu vũ trụ gần như có thể so sánh bất cứ thứ gì, thậm chí cả các vật thể. Cách các đối tượng được so sánh dựa trên loại đối tượng. Các lớp PHP dựng sẵn có thể xác định phép so sánh của riêng chúng, trong khi các đối tượng vùng người dùng được so sánh dựa trên các thuộc tính và giá trị của chúng.

Khi nào bạn muốn so sánh các đối tượng mà bạn yêu cầu? Thực ra có một ví dụ rất rõ ràng: ngày tháng.

$dateA = DateTime::createFromFormat('Y-m-d', '2000-02-01');

$dateB = DateTime::createFromFormat('Y-m-d', '2000-01-01');

$dateA <=> $dateB; // Returns 1

Tất nhiên, so sánh ngày tháng chỉ là một ví dụ, nhưng là một ví dụ rất hữu ích.

# Sắp xếp các chức năng

Một công dụng tuyệt vời cho toán tử này là sắp xếp các mảng. Có khá nhiều cách để sắp xếp một mảng trong PHP và một số phương pháp này cho phép một hàm sắp xếp do người dùng xác định. Chức năng này có để so sánh hai yếu tố, và trở lại 1, 0 hoặc -1 dựa trên vị trí của họ.

Một trường hợp sử dụng tuyệt vời cho người điều hành tàu vũ trụ!

$array = [5, 1, 6, 3];

usort($array, function ($a, $b) {
    return $a <=> $b;
});

// $array = [1, 3, 5, 6];

Để sắp xếp giảm dần, bạn chỉ cần đảo ngược kết quả so sánh:

usort($array, function ($a, $b) {
    return -($a <=> $b);
});

// $array = [6, 5, 3, 1];

Other

Theo stitcher.io

Tags:

Categories:

Updated:

Leave a Comment