Question

What is the best way to set a single variable when having multiple checks? There must be some efficient, precise, non-redundant, readable way to do this?

I rarely use Switch statements as I find them very redundant, often taking up 3-4 lines per check where you can often get away with a simple 1-2 line check, which adds up as you do more checks.

I was just reading that Switch statements are more readable compared to if/elseif/else blocks, and I can see how it is more readable due to alignment.

I enjoy using ternary statements because it allows you to use a single variable declaration, rather than writing redundant code, but a switch statement to me seems overly redundant plus its code(line consumption) overhead.

Hacked In Enum

class eUserType
{
    const Normal = 0;
    const Admin = 1;
    const Moderator = 2;
}

if elseif if

if ($userType == eUserType::Normal)
    $info = "Normal User";
elseif($userType == eUserType::Admin)
    $info = "Admin User";
elseif($userType == eUserType::Moderator)
    $info = "Moderator User";
else
    $info = false;

switch

switch($userType)
{
    case eUserType::Normal:
        $info = "Normal User";
        break;
    case eUserType::Admin:
        $info = "Admin User";
        break;
    case eUserType::Moderator:
        $info = "Moderator User";
        break;
    default:
        $info = false;
}

Ternary

I have never written a Ternary like this before, and went with my own whitespacing on it. It seems precise and efficient but I still find this to be very redundant with: "$userType == eUserType::". Plus I'm assuming most IDE's aren't going to handle the auto indent of code very well with this, as mine didn't (PHPStorm).

$info = $userType == eUserType::Normal ? 
            "Normal User" : 
        $userType == eUserType::Admin ? 
            "Admin User" : 
        $userType == eUserType::Moderator ? 
            "Moderator User" : false; 

I assume that I should be wrapping this into a function/method return the $info and not care what lies inside the function?

I'm wondering if there's some great way to do something like this that I haven't yet seen yet.

Ultimately what I think I'm looking for is a hybrid of Ternary's single variable setting with a switch statement's single variable check. (Doubtful it exists, but why not ask?)

Edit: I know that there's surely a way to use reflection to make this code dynamic if following a rigid pattern, but I used the data being set to $info as simple example data rather than the complex objects I'm working with. I'm thinking I'll end up tossing these checks into the User Class for any possible reusability.

Was it helpful?

Solution

How about using an array?

$labels = array(
  eUserType::Normal => "Normal User",
  ...
);

return isset($labels[$userType]) ? $labels[$userType] : false;

Yeah, it's possible with Reflection too (I wouldn't go this way though, you can't localize your strings this way):

$class = new ReflectionClass('eUserType');
$key   = array_search($userType, $class->getConstants());

return ($key !== false) ? sprintf('%s User', $key) : false;

OTHER TIPS

I think this is mostly subjective, but... don't use ternary:

"It is recommended that you avoid "stacking" ternary expressions. PHP's behaviour when using more than one ternary operator within a single statement is non-obvious:" - http://php.net/manual/en/language.operators.comparison.php

Otherwise, I have always found if statements to be more readable, since they are far more common and more familiar than switch: unless you have a very large number of choices. Adding a new switch is quicker than adding a new if/else block.

The performance argument for switch is: "In a switch statement, the condition is evaluated only once and the result is compared to each case statement. In an elseif statement, the condition is evaluated again. If your condition is more complicated than a simple compare and/or is in a tight loop, a switch may be faster." - http://php.net/manual/en/control-structures.switch.php

Your example is a "simple compare".

My last comment is that switch can be error prone, and accidental misuse can make debugging tedious. If you're using continue or break, or more accurately: intentionally NOT using continue or break sometimes, I find it easy to make mistakes and get lost in complicated logic.

So for my money, ternary for one-liners, if/else is all-purpose, go-to tool, unless I have very large or dynamic conditions, or the logic requires some behavior only switch can provide.

Ternary is for when you only have two possible values. The examples you posted should either be a switch or an if / else "ladder". It's really just a matter of preference. There is no definitive reason to use one over the other, unless of course there is more than one condition in each check (switch only checks one thing).

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top