简体   繁体   中英

PHP: switch with multiple conditions, a better more elegant way?

This is my current code, where if a given string starts with a specific letter I fire a function... simple...

      switch ($string[0]) {
        case 'a':
            //do   X
            break;
        case 'b':
             //do   Y
            break;
        case 'c':
            //do   Z
            break;
        case 'd':
            //do   X
            break;
//
// etc etc with all alphabet
//
        default:
            //do some
            break;
    }

but i'd like to fire a function X, if both a, b and c is met, and function Y if another group of letters match the conditions...

im wondering if there is a more elegante way to do it instead of a 26 letters switch..

I think i need to use preg_match , but not sure how...

I will make two suggestions:

  1. The switch syntax allows you to execute the same code for multiple cases by falling through (omitting a break between one case and the next).

     switch ($string[0]) { case 'a': case 'b': case 'c': handle_A_B_C(); break; case 'd': case 'e': handle_D_E(); break; // ...etc. } 
  2. I like to use in_array() to do multiple equality comparisons in an elegant, readable way.

     if (in_array($string[0], ['a', 'b', 'c'])) { handle_A_B_C(); } elseif (in_array($string[0], ['d', 'e'])) { handle_D_E(); } // ... etc. 

As noted by @devon below, you can substitute range('a', 'c') for ['a', 'b', 'c'] for readability. If you have cases that fire on more than two or three letters and the letters are always sequential, that would be a nice touch.

You can stack cases, however, you also want to be careful of using break. Break means it won't check any additional cases. If 'c' can perform both x() and y(), you'll want something like this:

switch ($string[0]) {
    case 'a':
    case 'b':
    case 'c':
        x();
    case 'c':
    case 'd':
        y();
}

In addition to the other answers, this also can be used, by defining a map/legend array and looping through it.

/*
Define legends function as a key,  letters array as value
*/
$legend=array (
    'process_abc'=>array('a','b','c'),
    'process_gpo'=>array('g','p','o')
);

/*
    loop through the legend and check if it exists within the array
*/
foreach ($legend as $function=>$letters){
     if (in_array($string[0],$letters)){
        call_user_func($function);
        break;
     }
}


function process_abc(){
    echo "ABC was called";  
}

function process_gpo(){
    echo "GPO was called";  
}

You could also use the switch like this:

$char = 'z';
switch (true) {
    case strpos('abcdef', $char) !== -1:
        echo 'Do A';
    break;
    case strpos('ghijkl', $char) !== -1:
        echo 'Do B';
    break;
    case strpos('mnopqr', $char) !== -1:
        echo 'Do C';
    break;
    case strpos('stuvw', $char) !== -1:
        echo 'Do D';
    break;
    case strpos('xyz', $char) !== -1:
        echo 'Do E';
    break;
}

Or group the case s:

switch ($char) {
    case 'a':
    case 'b':
    case 'c':
        echo 'Do A';
    break;
    case 'd':
    case 'e':
    // ...
        echo 'Do B';
    break;
    // ...
}

Or this:

$actions = [
    'abcde':  function () { return 'Do A'; },
    'fghij':  function () { return 'Do B'; },
    'klmno':  function () { return 'Do C'; },
    'pqrst':  function () { return 'Do D'; },
    'uvwxyz': function () { return 'Do E'; },
];
$char = 'n';
foreach ($actions as $haystack => $callback) {
    if (strpos($haystack, $char) !== -1) {
        echo $callback();
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM