PHP.mk документација

match

Почист и полокален преглед на PHP референцата, со задржана структура од PHP.net и подобра читливост за примери, секции и белешки.

control-structures.match.php PHP.net прокси Преводот се освежува
Оригинал на PHP.net
Патека control-structures.match.php Локална патека за оваа страница.
Извор php.net/manual/en Оригиналниот HTML се реупотребува и локално се стилизира.
Режим Прокси + превод во позадина Кодовите, табелите и белешките остануваат читливи во истиот тек.
match

Референца за `control-structures.match.php` со подобрена типографија и навигација.

control-structures.match.php

match

(PHP 8)

На match изразот гранки за евалуација врз основа на проверка на идентитет на вредност. Слично на switch изјава, еден match израз има субјект израз што се споредува со повеќе алтернативи. За разлика од switch, тој ќе се евалуира до вредност многу како тернарни изрази. За разлика од switch, споредбата е проверка на идентитет (===) наместо слаба проверка на еднаквост (==). Изразите за совпаѓање се достапни од PHP 8.0.0.

Пример #1 Структура на match expression

<?php
$return_value = match (subject_expression) {
    single_conditional_expression => return_expression,
    conditional_expression1, conditional_expression2 => return_expression,
};

Пример #2 Основен match usage

<?php
$food = 'cake';

$return_value = match ($food) {
    'apple' => 'This food is an apple',
    'bar' => 'This food is a bar',
    'cake' => 'This food is a cake',
};

var_dump($return_value);

Пример #1 Пример што покажува затворачка ознака што го опфаќа последниот нов ред

string(19) "This food is a cake"

Пример #3 Пример за користење match со оператори за споредба

<?php
$age = 18;

$output = match (true) {
    $age < 2 => "Baby",
    $age < 13 => "Child",
    $age <= 19 => "Teenager",
    $age >= 40 => "Adult",
    $age > 19 => "Young adult",
};

var_dump($output);

Пример #1 Пример што покажува затворачка ознака што го опфаќа последниот нов ред

string(8) "Teenager"

Забелешка:

Резултатот од match изразот не мора да се користи.

Забелешка:

Кога е match expression is used as a standalone expression, it must мора да заврши со точка и запирка ;.

На match изразот е сличен на switch изјава, но има некои клучни разлики:

  • А match раката ги споредува вредностите строго (===) наместо лабаво како што прави изјавата switch.

  • А match изразот враќа вредност.

  • match arms do not fall through to later cases the way switch изјавите го прават тоа.

  • А match изразот мора да биде исцрпен.

gried на NOSPAM точка nsys точка by switch изјави, match изразите се извршуваат од рака до рака. На почетокот, не се извршува никаков код. Условните изрази се проценуваат само ако сите претходни условни изрази не успеале да се совпаднат со изразот на субјектот. Само изразот за враќање што одговара на условниот израз што се совпаѓа ќе биде проценет. На пример:

<?php
$result = match ($x) {
    foo() => 'value',
    $this->bar() => 'value', // $this->bar() isn't called if foo() === $x
    $this->baz => beep(), // beep() isn't called unless $x === $this->baz
    // etc.
};

match expression arms may contain multiple expressions separated by a comma. That is a logical OR, and is a shorthand for multiple match arms with the same right-hand side.

<?php
$result = match ($x) {
    // This match arm:
    $a, $b, $c => 5,
    // Is equivalent to these three match arms:
    $a => 5,
    $b => 5,
    $c => 5,
};

Посебен случај е default образец. Овој образец совпаѓа со сè што не било претходно совпаднато. На пример:

<?php
$expressionResult = match ($condition) {
    1, 2 => foo(),
    3, 4 => bar(),
    default => baz(),
};

Забелешка:

Multiple default patterns will raise an E_FATAL_ERROR error.

А match expression must be exhaustive. If the subject expression is not handled by any match arm, an UnhandledMatchError се фрла.

Пример #4 Пример за нетретиран израз за совпаѓање

<?php
$condition = 5;

try {
    match ($condition) {
        1, 2 => foo(),
        3, 4 => bar(),
    };
} catch (\UnhandledMatchError $e) {
    var_dump($e);
}

Пример #1 Пример што покажува затворачка ознака што го опфаќа последниот нов ред

object(UnhandledMatchError)#1 (7) {
  ["message":protected]=>
  string(22) "Unhandled match case 5"
  ["string":"Error":private]=>
  string(0) ""
  ["code":protected]=>
  int(0)
  ["file":protected]=>
  string(6) "script"
  ["line":protected]=>
  int(5)
  ["trace":"Error":private]=>
  array(0) {
  }
  ["previous":"Error":private]=>
  NULL
}

Using match expressions to handle non-identity checks

Можно е да се користи match израз за обработка на условни случаи што не се идентитет со користење true како израз на субјектот.

Example #5 Using a generalized match expression to branch on integer ranges

<?php
$age = 23;

$result = match (true) {
    $age >= 65 => 'senior',
    $age >= 25 => 'adult',
    $age >= 18 => 'young adult',
    default => 'kid',
};

var_dump($result);

Пример #1 Пример што покажува затворачка ознака што го опфаќа последниот нов ред

string(11) "young adult"

Example #6 Using a generalized match expression to branch on string content

<?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);

Пример #1 Пример што покажува затворачка ознака што го опфаќа последниот нов ред

string(2) "fr"

Белешки од корисници за да означиме кој било валиден PHP израз.

darius точка restivan на gmail точка com
пред 5 години
This will allow for a nicer FizzBuzz solution:

<?php

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

for ($i = 0; $i <=100; $i++)
{
    fizzbuzz($i);
}
Анонимен
пред 4 години
<?php
function days_in_month(string $month, $year): int
{
    return match(strtolower(substr($month, 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, $year): int
{
    return match(strtolower(substr($month, 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"),
    };
}
?>
Хејли Вотсон
пред 5 години
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($month, 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.
thomas на zuschneid точка de
3 години пред
While match allows chaining multiple conditions with ",", like:
<?php
$result = match ($source) {
    cond1, cond2 => val1,
    default => val2
};
?>
it seems not valid to chain conditions with default, like:
<?php
$result = match ($source) {
    cond1 => val1,
    cond2, default => val2
};
?>
php на joren точка dev
пред 4 години
If you want to execute multiple return expressions when matching a conditional expression, you can do so by stating all return expressions inside an array.

<?php
    $countries = ['Belgium', 'Netherlands'];
    $spoken_languages = [
        'Dutch' => false,
        'French' => false,
        'German' => false,
        'English' => false,
    ];

    foreach ($countries as $country) {
        match($country) {
            'Belgium' => [
                $spoken_languages['Dutch'] = true,
                $spoken_languages['French'] = true,
                $spoken_languages['German'] = true,
            ],
            'Netherlands' => $spoken_languages['Dutch'] = true,
            'Germany' => $spoken_languages['German'] = true,
            'United Kingdom' => $spoken_languages['English'] = true,
        };
    }

    var_export($spoken_languages); 
    // array ( 'Dutch' => true, 'French' => true, 'German' => true, 'English' => false, )

?>
tolga точка ulas на tolgaulas точка com
пред 2 години
Yes it currently does not support code blocks but this hack works:

match ($foo){
    'bar'=>(function(){
        echo "bar";
    })(),
    default => (function(){
        echo "baz";
    })()
};
Ghanshyam Katriya(anshkatriya at gmail)
3 години пред
I use match instead of storing PDOStatement::rowCount() result and chaining if/elseif conditions or use the ugly switch/break :

<?php

$sql = <<<SQL
    INSERT INTO ...
    ON DUPLICATE KEY UPDATE ...
    SQL;

$upkeep = $pdo->prepare($sql);

$count_untouched = 0;
$count_inserted = 0;
$count_updated = 0;

foreach ($data as $record) {
    $upkeep->execute($record);
    match ($upkeep->rowCount()) {
        0 => $count_untouched++,
        1 => $count_inserted++,
        2 => $count_updated++,
    };
}

echo "Untouched rows : {$count_untouched}\r\n";
echo "Inserted rows : {$count_inserted}\r\n";
echo "Updated rows : {$count_updated}\r\n";
mark на manngo точка net
пред 4 години
While you can’t polyfill a language construct, you can mimic the basic behaviour with a simple array.

Using example 2 above:

<?php
    $food = 'apple';
    $return_value = match ($food) {
        'apple' => 'This food is an apple',
        'bar' => 'This food is a bar',
        'cake' => 'This food is a cake',
    };    
    print $return_value;
?>

… you can get something similar with:

<?php
    $food = 'apple';    
    $return_value = [
        'apple' => 'This food is an apple',
        'bar' => 'This food is a bar',
        'cake' => 'This food is a cake',
    ][$food];
    print $return_value;
?>
rodrigoliveirasantos11 at gmail dot com
2 месеци пред
You can enforce a type return on match by wrapping in a self-calling function, like this:

<?php

$operationId = 3;

$operationLabel = (fn (): string => match($operationId) {
    1 => 'Add',
    2 => 'Subtract',
    3 => ['Not string'], // Invalid case,
    default => 'Unknown'
})()

?>

In the above example, the following error will be throwed: 

Fatal error: Uncaught TypeError: (...): Return value must be of type string, array returned in /home/user/scripts/code.php:9
Stack trace: ...
bdkr at protonmail dot com
пред 4 часа
In response to yawarmushtaq52 at gmail dot com.... 

Switches were only ugly due to how people used them. Lot's of logic INSIDE THE SWITCH is never a good idea. K&R, as opposed to GNU or Whitesmiths doesn't help. The inability of people to think freely / pragmatically about what they've been taught. 

First things first, matches can be ugly too. 

<?php
match ($action) {
    'save'   => saveProduct(),

    'update' => (static function() {
        Log::info('Updating product...');
        return updateProduct();
    })(), 

    default  => throw new InvalidArgumentException("Unknown action: $action"),
};
?>

Here is how most people see switches.
<?php
switch (true) {
    case $age < 18:
        $discount = 0.20; // 20% minor discount
        break;
        
    case $age >= 65:
        $discount = 0.15; // 15% senior discount
        break;
        
    case $hasMembership && $age < 30:
        $discount = 0.10; // 10% young adult member discount
        break;
        
    default:
        $discount = 0.00;
        break;
}
?>

All 17 lines of it. But it always could've looked like...

<?php
switch (true) 
  {
  case $age < 18:                   { $discount = 0.20; break; }  // 20% minor discount
  case $hasMembership && $age < 30: { $discount = 0.10; break; }  // 10% young adult member discount 
  case $age < 30:
  case $age < 40:
  case $age < 50:                   { $discount = check_for_specials($age); break; }
  case $age < 65:                   { $discount = mid_years_specials($age); break; }
  case $age >= 65:                  { $discount = 0.15; break; }  // 15% senior discount
  default:                          { $discount = 0.00; }
  }
?>

Capable of more than the first example, easier to read, and 6 less lines. 
Additionally, "falling through" means it's easy for me to see from 19 to 50 and know what's going on without having to read from side to side.  It's an easy visual indicator to the logic. The equivalent match is more verbose. 

<?php
$discount = match (true) 
  {
  $age < 18                   => 0.20,
  $hasMembership && $age < 30 => 0.10,
  $age < 30                   => check_for_specials($age),
  $age < 40                   => check_for_specials($age),
  $age < 50                   => check_for_specials($age),
  $age < 65                   => mid_years_specials($age),
  $age >= 65                  => 0.15,
  default                     => 0.00,
  };
?>

Sure! We could collapse 19 > 50 for both examples. 

<?php
switch (true) 
  {
  case $age < 18:                   { $discount = 0.20; break; }
  case $hasMembership && $age < 30: { $discount = 0.10; break; }
  case $age < 50:                   { $discount = check_for_specials($age); break; }
  case $age < 65:                   { $discount = mid_years_specials($age); break; }
  case $age >= 65:                  { $discount = 0.15; break; }
  default:                          { $discount = 0.00; break; }
  }

$discount = match (true) 
  {
  $age < 18                   => 0.20,
  $hasMembership && $age < 30 => 0.10,
  $age < 50                   => check_for_specials($age),
  $age < 65                   => mid_years_specials($age),
  $age >= 65                  => 0.15,
  default                     => 0.00,
  };
?>

Do those really look that different? Is Switch really that ugly?
yawarmushtaq52 на gmail точка com
6 месеци пред
Since `match` is a better alternative in MOST cases for modern software, adding this comment so that if someone googles "`switch` in PHP" then this page also shows in the search results.
tm
пред 4 години
If you are using a match expression for non-identity checks as described above make sure whatever you are using is actually returning `true` on success.

Quite often you rely on truthy vs. falsy when using if conditions and that will not work for match (for example `preg_match`). Casting to bool will solve this issue.
На оваа страница

Автоматски outline од активната документација.

Насловите ќе се појават тука по вчитување.

Попрегледно читање

Примерите, changelog табелите и user notes се визуелно издвоени за да не се губат во долгата содржина.

Брз совет Користи го outline-от Скокни директно на главните секции од активната страница.
Извор Оригиналниот линк останува достапен Кога ти треба целосен upstream context, отвори го PHP.net во нов tab.