Incorporating match expressions into your program code
Among the many incredibly useful features introduced in PHP 8, match expressions definitely stand out. Match
expressions are a more accurate shorthand syntax that can potentially replace the tired old switch
statement that came directly from the C language. In this section, you will learn how to produce cleaner and more accurate program code by replacing switch
statements with match
expressions.
Match expression general syntax
Match
expression syntax is much like that of an array, where the key is the item to match and the value is an expression. Here is the general syntax for match
:
$result = match(<EXPRESSION>) { <ITEM> => <EXPRESSION>, [<ITEM> => <EXPRESSION>,] default => <DEFAULT EXPRESSION> };
The expression must be a valid PHP expression. Examples of expressions could include any of the following:
- A specific value (for example,
"some text"
) - An operation (for example,
$a + $b
) - An anonymous function or class
The only limitation is that the expression has to be defined in a single line of code. Major differences between match
and switch
are summarized here:
Other than the differences noted, match
and switch
both allow case aggregation, as well as providing support for a default case.
switch and match examples
Here is a simple example that renders a currency symbol using switch
:
// /repo/ch01/php7_switch.php function get_symbol($iso) { switch ($iso) { case 'CNY' : $sym = '¥'; break; case 'EUR' : $sym = '€'; break; case 'EGP' : case 'GBP' : $sym = '£'; break; case 'THB' : $sym = '฿'; break; default : $sym = '$'; } return $sym; } $test = ['CNY', 'EGP', 'EUR', 'GBP', 'THB', 'MXD']; foreach ($test as $iso) echo 'The currency symbol for ' . $iso . ' is ' . get_symbol($iso) . "\n";
When this code is executed, you see the currency symbols for each of the International Organization for Standardization (ISO) currency codes in the $test
array. The same result as that shown in the preceding code snippet can be obtained in PHP 8, using the following code:
// /repo/ch01/php8_switch.php function get_symbol($iso) { return match ($iso) { 'EGP','GBP' => '£', 'CNY' => '¥', 'EUR' => '€', 'THB' => '฿', default => '$' }; } $test = ['CNY', 'EGP', 'EUR', 'GBP', 'THB', 'MXD']; foreach ($test as $iso) echo 'The currency symbol for ' . $iso . ' is ' . get_symbol($iso) . "\n";
Both examples produce an identical output, as illustrated here:
The currency symbol for CNY is ¥ The currency symbol for EGP is £ The currency symbol for EUR is € The currency symbol for GBP is £ The currency symbol for THB is ฿ The currency symbol for MXD is $
As mentioned previously, both code examples produce a list of currency symbols for the list of ISO currency codes stored in the $test
array.
Complex match example
Returning to our CAPTCHA project, assume that we wish to introduce distortion to make the CAPTCHA characters more difficult to read. To accomplish this goal, we introduce a number of strategy classes, each producing a different distortion, as summarized in this table:
After randomizing the list of strategies to be employed, we use a match
expression to execute the results, as follows:
- First we define an autoloader, import the classes to be used, and list potential strategies to employ, as illustrated in the following code snippet:
// /repo/ch01/php8_single_strategies.php // not all code is shown require_once __DIR__ . '/../src/Server/Autoload/Loader.php'; $loader = new \Server\Autoload\Loader(); use Php8\Image\SingleChar; use Php8\Image\Strategy\ {LineFill,DotFill,Shadow,RotateText}; $strategies = ['rotate', 'line', 'line', 'dot', 'dot', 'shadow'];
- Next, we generate the CAPTCHA phrase, as follows:
$phrase = strtoupper(bin2hex(random_bytes(NUM_BYTES))); $length = strlen($phrase);
- We then loop through each character in the CAPTCHA phrase and create a
SingleChar
instance. The initial call towriteFill()
creates the white background canvas. We also need to callshuffle()
to randomize the list of distortion strategies. The process is illustrated in the following code snippet:$images = []; for ($x = 0; $x < $length; $x++) { $char = new SingleChar($phrase[$x], FONT_FILE); $char->writeFill(); shuffle($strategies);
- We then loop through the strategies and layer distortions upon the original image. This is where the
match
expression comes into play. Notice that one strategy needs additional lines of code. Becausematch
can only support a single expression, we simply wrap the multiple lines of code into an anonymous function, as follows:foreach ($strategies as $item) { $func = match ($item) { 'rotate' => RotateText::writeText($char), 'line' => LineFill::writeFill( $char, rand(1, 10)), 'dot' => DotFill::writeFill($char, rand(10, 20)), 'shadow' => function ($char) { $num = rand(1, 8); $r = rand(0x70, 0xEF); $g = rand(0x70, 0xEF); $b = rand(0x70, 0xEF); return Shadow::writeText( $char, $num, $r, $g, $b);}, 'default' => TRUE }; if (is_callable($func)) $func($char); }
- All that remains to be done is to overlay the image with the actual CAPTCHA phrase by calling
writeText()
with no arguments. After that, we save the distorted image as a Portable Network Graphics (PNG) file for display, as illustrated in the following code snippet:$char->writeText(); $fn = $x . '_' . substr(basename(__FILE__), 0, -4) . '.png'; $char->save(IMG_DIR . '/' . $fn); $images[] = $fn; } include __DIR__ . '/captcha_simple.phtml';
Here is the result, running the preceding example from a browser that points to the Docker container associated with this book:
Next, we'll have a look at another really great feature: named arguments.
Tip
You can see the original proposal for match
expressions here: https://wiki.php.net/rfc/match_expression_v2