Using comparison operators in a PHP 'switch' statement

PhpSwitch Statement

Php Problem Overview


I have four conditions that I need to go through and I thought it would be best to use the switch statement in PHP. However, I need to check whether an integer is, let's say, less than or equal, or greater than and equal.

switch ($count) {
    case 20:
        $priority = 'low';
        break;

    case 40:
        $priority = 'medium';
        break;

    case 60:
        $priority = 'high';
        break;

    case 80:
        $priority = 'severe';
        break;
}

With an if() statement it would look like the following:

if ($count <= 20) {
    $priority = 'low';
} elseif ($count <= 40) {
    $priority = 'medium';
} elseif ($count <= 60) {
    $priority = 'high';
} else {
    $priority = 'severe';
}

Is that possible in switch-case?

Php Solutions


Solution 1 - Php

A more general case for solving this problem is:

switch (true) {
    case $count <= 20:
        $priority = 'low';
        break;

    case $count <= 40:
        $priority = 'medium';
        break;

    case $count <= 60:
        $priority = 'high';
        break;

    default:
        $priority = 'severe';
        break;
}

Solution 2 - Php

Switches can't do that, but in this particular case you can do something like this:

switch ((int)(($count - 1) / 20)) {
    case 0:
        $priority = 'low';
        break;
    case 1:
        $priority = 'medium';
        break;
    case 2:
        $priority = 'high';
        break;
    case 3:
        $priority = 'severe';
        break;
}

So in (int)(($count - 1) / 20) all values from 0 to 20 will eval to 0, 21 to 40 will eval to 1 and so on, allowing you to use the switch statement for this purpose.

And since we are concatenating values, we can even simplify to an array:

$priorities = ['low', 'medium', 'high', 'severe'];
$priority = $priorities[(int)(($count - 1) / 20)];

Solution 3 - Php

There is a way that works in PHP 7 using ternary assignment operators. The operator was introduced earlier on (5.4?), but I never tested the code on other versions. I wrote the whole switch code there, however for brevity here is just the specific clause. Let's say we want the condition to match for all numbers greater than or equal to five:

switch($value){
    case ($value >= 5 ? $value : !$value): // Do something here
    break;
}

We either allow the $value to pass unchanged or we negate the value according to the condition. A $value will always match itself or fail the test against its negation.

Solution 4 - Php

No. switch() statements are for doing multiple equality tests. They're basically just a slightly easier to read (but also more hazardous) version of

if (x == 'a') { ... }
else if (x == 'b') { ... } 
else if (x == 'c') { ... }

code. There is no way to change a switch() away from == to < or any other comparison operator. It's strictly for equality testing.

Solution 5 - Php

Using the ternary operator:

$priority =
    // "switch" comparison for $count
    $count <= 20 ? 'low' :
    ($count <= 40 ? 'medium' :
    ($count <= 60 ? 'high' :
    // default above 60
    'severe'));

I know the common complaint that ternary operators can be hard to understand, but this is just too easy to do with a simple ?:.

It operates like the Excel "If" formula:

=IF( logical_test, value_if_true, value_if_false )
$variable = logical_test ? value_if_true : value_if_false

And you can nest the if statements (place a second ?: in the 'value_if_false' section of the first one), which is certainly where it can become confusing to read, but less so when you write it out line by line, as above.

My code above is basically equivalent to the if() statement written by the OP.

Solution 6 - Php

I can also confirm bytepunk's answer here is functional.

Also, expending the concept with PHP 7:

switch ($interval->days)
{
    case 0:
        return '1 day';
        // break;
    case (($interval->days >= 1 && $interval->days <= 7) ?? $interval->days):
        return '1 week';
        // break;
    case (($interval->days >= 8 && $interval->days <= 31) ?? $interval->days):
        return '1 month';
        // break;
    case (($interval->days >= 31 && $interval->days <= 93) ?? $interval->days):
        return '2-3 months';
        // break;
    default:
        return '3+ months';
}

I will admit that this isn't the cleanest of code, so perhaps wrapping each case with a static-like pure function would neat things up a bit, and not forgetting to name each function (or create one generic function with parameters) to match the case. This will make it more readable.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionJessie StalkView Question on Stackoverflow
Solution 1 - PhpKonr NessView Answer on Stackoverflow
Solution 2 - PhpHavenardView Answer on Stackoverflow
Solution 3 - PhpbytephunkView Answer on Stackoverflow
Solution 4 - PhpMarc BView Answer on Stackoverflow
Solution 5 - PhpmilkncookieView Answer on Stackoverflow
Solution 6 - PhptfontView Answer on Stackoverflow