PHP 7.4.24 Released!

match

(PHP 8)

match (eşleşme) ifadesi, bir değerin özdeşlik denetimine dayalı olarak değerlendirmesini dallara ayırır. Switch deyimine benzer şekilde, bir match ifadesinin birden çok alternatifle karşılaştırılan bir özne ifadesi vardır. switch'in aksine, üçlü ifadeler gibi bir değere indirgeyecektir. switch aksine, karşılaştırma zayıf bir eşitlik denetiminden (==) ziyade bir özdeşlik denetimidir (===). Eşleşme ifadeleri PHP 8.0.0'dan itibaren mevcuttur.

Örnek 1 match ifadesinin yapısı

<?php
$dönüş değeri 
match (özne_ifade) {
    
tekil_koşullu_ifade => dönüş_ifadesi,
    
koşullu_ifade1koşullu_ifade2 => dönüş_ifadesi,
};
?>

Bilginize: match ifadesinin sonucunun kullanılmasına gerek yoktur.

Bilginize: match ifadesi mutlaka bir noktalı virgül ; ile sonlandırılmalıdır.

match ifadesi switch deyimine benzemekle birlikte bazı önemli farklar vardır:

  • Bir match kolu, değeri birebir (===) değerlendirir, switch deyimin yaptığı gibi gevşekçe değil.
  • match ifadesi bir değer döndürür.
  • match kolları switch deyimlerini yaptığı gibi sonraki durumlarda başarısız olmaz.
  • match ifadesi kapsamlı olmalıdır.

switch deyimleri gibi, match ifadeleri de eşleşmeleri sırayla değerlendirir. Başlangıçta hiçbir kod çalıştırılmaz. Koşullu ifadeler yalnızca, tüm önceki koşullu ifadeler özne ifadeyle eşleşmede başarısız olmuşlarsa değerlendirilir. Yalnızca eşleşen koşullu ifadeye karşılık gelen dönüş ifadesi değerlendirilir. Örneğin:

<?php
$sonuç 
match ($x) {
    
foo() => ...,
    
$this->bar() => ..., //  foo() === $x ise $this->bar çağrılmaz
    
$this->baz => beep(), // $x === $this->baz olmadıkça beep() çağrılmaz
    // vb.
};
?>

match ifadesinin kolları virgüllerle ayrılmış çok sayıda ifade içerebilir. Bu bir mantıksal VEYA olup, aynı sağ taraflı çok sayıda eşleşme kolu için bir kısa yoldur.

<?php
$sonuç 
match ($x) {
    
// Bu eşleşme kolu:
    
$a$b$c => 5,
    
// Aşağıdaki üç eşleşme koluna eşdeğerdir:
    
$a => 5,
    
$b => 5,
    
$c => 5,
};
?>

Özel bir durum default kalıbıdır. Bu kalıp evvelce eşleşmemiş herşeyle eşleşir. Örnek:

<?php
$ifadeSonucu 
match ($koşul) {
    
1=> foo(),
    
3=> bar(),
    default => 
baz(),
};
?>

Bilginize: Çok sayıda default kalıbı bir E_FATAL_ERROR hatasına (ölümcül hataya) yol açar.

match ifadesi kapsamlı olmalıdır. Konu ifadesi herhangi bir eşleşme kolu tarafından işlenmezse, bir UnhandledMatchError (başarısız eşleşme hatası) yavrulanır.

Örnek 2 - Başarısız eşleşme hatası örneği

<?php
$özne 
5;

try {
    
match ($özne) {
        
1=> foo(),
        
3=> bar(),
    };
} catch (\
UnhandledMatchError $e) {
    
var_dump($e);
}
?>

Yukarıdaki örneğin çıktısı:

object(UnhandledMatchError)#1 (7) {
  ["message":protected]=>
  string(33) "Unhandled match value of type int"
  ["string":"Error":private]=>
  string(0) ""
  ["code":protected]=>
  int(0)
  ["file":protected]=>
  string(9) "/in/ICgGK"
  ["line":protected]=>
  int(6)
  ["trace":"Error":private]=>
  array(0) {
  }
  ["previous":"Error":private]=>
  NULL
}

- Başarısız eşleşmeleri işlemek için match ifadelerin kullanımı

Özne ifadesi olarak true kullanarak özdeş olmayan koşullu durumları ele almak için bir match ifadesi kullanmak mümkündür.

Örnek 3 - Tamsayı aralıklarında dallanmak için genelleştirilmiş eşleşme ifadelerinin kullanılması

<?php

$yaş 
23;

$result match (true) {
    
$yaş >= 65 => 'yaşlı',
    
$yaş >= 25 => 'yetişkin',
    
$yaş >= 18 => 'genç',
    default => 
'çocuk',
};

var_dump($result);
?>

Yukarıdaki örneğin çıktısı:

string(11) "genç"

Örnek 4 - Dize içeriklerde dallanmak için genelleştirilmiş eşleşme ifadelerinin kullanılması

<?php

$text 
'Bienvenue chez nous';

$result match (true) {
    
str_contains($text'Welcome') || str_contains($text'Hello') => 'en',
    
str_contains($text'Bienvenue') || str_contains($text'Bonjour') => 'fr',
    
// ...
};

var_dump($result);
?>

Yukarıdaki örneğin çıktısı:

string(2) "fr"
add a note add a note

User Contributed Notes 5 notes

up
29
Hayley Watson
9 months ago
As well as being similar to a switch, match expressions can be thought of as enhanced lookup tables — for when a simple array lookup isn't enough without extra handling of edge cases, but a full switch statement would be overweight.

For a familiar example, the following
<?php

function days_in_month(string $month): int
{
    static
$lookup = [
   
'jan' => 31,
   
'feb' => 0,
   
'mar' => 31,
   
'apr' => 30,
   
'may' => 31,
   
'jun' => 30,
   
'jul' => 31,
   
'aug' => 31,
   
'sep' => 30,
   
'oct' => 31,
   
'nov' => 30,
   
'dec' => 31
   
];

   
$name = strtolower(substr($name, 0, 3));

    if(isset(
$lookup[$name])) {
        if(
$name == 'feb') {
            return
is_leap($year) ? 29 : 28;
        } else {
            return
$lookup[$name];
        }
    }
    throw new
InvalidArgumentException("Bogus month");
}

?>

with the fiddly stuff at the end, can be replaced by

<?php
function days_in_month(string $month): int
{
    return
match(strtolower(substr($name, 0, 3))) {
       
'jan' => 31,
       
'feb' => is_leap($year) ? 29 : 28,
       
'mar' => 31,
       
'apr' => 30,
       
'may' => 31,
       
'jun' => 30,
       
'jul' => 31,
       
'aug' => 31,
       
'sep' => 30,
       
'oct' => 31,
       
'nov' => 30,
       
'dec' => 31,
        default => throw new
InvalidArgumentException("Bogus month"),
    };
}
?>

Which also takes advantage of "throw" being handled as of PHP 8.0 as an expression instead of a statement.
up
11
darius dot restivan at gmail dot com
5 months ago
This will allow for a nicer FizzBuzz solution:

<?php

function fizzbuzz($num) {
    print
match (0) {
       
$num % 15 => "FizzBuzz" . PHP_EOL,
       
$num % => "Fizz" . PHP_EOL,
       
$num % => "Buzz" . PHP_EOL,
        default   =>
$num . PHP_EOL,
    };
}

for (
$i = 0; $i <=100; $i++)
{
   
fizzbuzz($i);
}
up
5
Anonymous
17 days ago
<?php
function days_in_month(string $month): int
{
    return
match(strtolower(substr($name, 0, 3))) {
       
'jan' => 31,
       
'feb' => is_leap($year) ? 29 : 28,
       
'mar' => 31,
       
'apr' => 30,
       
'may' => 31,
       
'jun' => 30,
       
'jul' => 31,
       
'aug' => 31,
       
'sep' => 30,
       
'oct' => 31,
       
'nov' => 30,
       
'dec' => 31,
        default => throw new
InvalidArgumentException("Bogus month"),
    };
}
?>

can be more concisely written as

<?php
function days_in_month(string $month): int
{
    return
match(strtolower(substr($name, 0, 3))) {
       
'apr', 'jun', 'sep''nov'  => 30,       
       
'jan', 'mar', 'may', 'jul', 'aug''oct', 'dec'  => 31,
       
'feb' => is_leap($year) ? 29 : 28,
        default => throw new
InvalidArgumentException("Bogus month"),
    };
}
?>
up
13
webmaster at warkensoft dot com
6 months ago
In the "familiar example" presented by Hayley Watson the following code is incorrect:

strtolower(substr($name, 0, 3))

It should instead be written in both instances as:

strtolower(substr($month, 0, 3))
up
6
lewiscowles at me dot com
5 months ago
The comment correcting Hayley's example misses that year is also present in the example, but not a function argument.

Most code from PHP.net should not be copied without user care. It was nonetheless, a great example of using short syntax to reduce complexity.
To Top