11

Consider:

I have a variable called $field that from time to time may have, among others, values such as action, id, and another_term. I want to use a switch structure to sift the values:

switch ($field) {
    case 'action':
        // do something
        break;
    case 'id':
        // do something
        break;
    case (strpos($field, '_term')):
        // do something else
        break;
}

The first two cases work. The third does not. I am thinking that this is an incorrect use of a switch statement. Is this better handled as an if/else sequence?

Steve Cooke
  • 447
  • 1
  • 4
  • 14

2 Answers2

30

You can do it using the switch statement like this:

$field = 'bla bla_term bla';

switch (true) {
    case $field === 'action':
        echo 'action';
    break;
    case $field === 'id':
        echo 'id';
    break;
    case strpos($field, '_term') >= 0:
        echo '_term';
    break;
}

The switch statement just compares the expressions in each case block to the value in the switch parentheses.

Expressions are units of code that you can reduce to a value, such as 2 + 3 or strpos(...). In PHP most things are expressions.

Here is an annotated version of the above example:

// We are going to compare each case against
// the 'true' value
switch (true) {

    // This expression returns true if $field
    // equals 'action'
    case $field === 'action':
        echo 'action';
    break;

    // This expression returns true if $field
    // equals 'id'
    case $field === 'id':
        echo 'id';
    break;

    // This expression returns true if the
    // return value of strpos is >= 0
    case strpos($field, '_term') >= 0:
        echo '_term';
    break;
}

If you want to use the return value of the strpos call then you can just assign it (assignments are expressions in PHP):

case ($pos = strpos($field, '_term')) >= 0:
    echo '_term at position ' . $pos;
break;
Sverri M. Olsen
  • 13,055
  • 3
  • 36
  • 52
  • Thank you - this is exactly what I am trying to do. – Steve Cooke Nov 07 '15 at 23:50
  • For others, although this solution meets my needs, `another_terminator_movie` is also true in the third case. If you need to be explicit that `_term` is the last part of the string being tested, then either something like MiDri's answer here, or one of these [http://stackoverflow.com/a/4764912/1389927] may be more appropriate. – Steve Cooke Nov 08 '15 at 00:32
  • 2
    I would say that you should compare last case with !== false because strpos can return 0 if substring doesn't exist: - from php.net: This function may return Boolean FALSE, but may also return a non-Boolean value which evaluates to FALSE. Please read the section on Booleans for more information. Use the === operator for testing the return value of this function. – 6opko May 30 '18 at 00:11
1

switch is just a sort of if x == y with y being any of the matching cases.

case (strpos($field, '_term')) would result in a -1 if match is not found or the point where "_term" was found (0 through string length -1 ) and not the field name.

If you're looking to catch anything with there phrase "_term" in the field do

$matches = array();
if(preg_match('/(.+)_term$/', $field, $matches)) {
    $field = $matches[1];
}

this will replace the field value "address_term" or what ever "something_term" to just "address" or "something"

MiDri
  • 747
  • 3
  • 13
  • Yes - you are right. Strpos returns the position or -1 rather than the string, so the case will never match. Ok, I'll rethink what to use in place of strpos – Steve Cooke Nov 07 '15 at 23:39
  • I updated my response with what I think you're wanting to do, but I'm not sure. You can do the reverse as and do "/.+(_term)$/" as the expression and it will turn anything ending in "_term" to just "_term" so you can use a switch statement case "_term": – MiDri Nov 07 '15 at 23:40