How to read spagetti php shorthand if statement ( ternary operators) and conver it into if and else statement

103 Views Asked by At

Someone wrote this 'stunning' short hand encapsulated statement. I am sure its not even suppose to be done like this, but I want to dissect it for someone else (myself as well) to be able to understand it well by break it down into if and else statement. I wonder where exactly is the way it should be broke down the statement with. the ? and : position really confused me and make me can get down to nowhere! (i.e. there is ? after another ? how that could be?

$cust->is_company() ? 'TekCustomer__'.($cust->getID() ? $cust->getID() : 'new'.($next_new_id-1)) : 'Person__'.($cust->people[0]->getID() ? $cust->people[0]->getID() : 'new'.$next_new_id++) 
6

There are 6 best solutions below

0
Jim On BEST ANSWER

I would highly recommend against the use of nested ternary operators. As you have found out they are far from readable. Converting to proper if statements here will certainly make it more readable. We can start by formatting it a bit to help break it down:

$cust->is_company() ? 
    'TekCustomer__'.($cust->getID() ? $cust->getID() : 'new'.($next_new_id-1)) :
     'Person__'.($cust->people[0]->getID() ? $cust->people[0]->getID() : 'new'.$next_new_id++)

Aha! It's actually not quote as horrible as it first looks (especially due to PHP's odd behaviour on nested ternarys*).

First off it's checking $cust->is_company() and doing one of two things. This gives us:

if($cust->is_company()){
    'TekCustomer__'.($cust->getID() ? $cust->getID() : 'new'.($next_new_id-1));
}else{
    'Person__'.($cust->people[0]->getID() ? $cust->people[0]->getID() : 'new'.$next_new_id++)
}

Note here that generally you would do something with the values. This will depend on how the expression was originally used.

I'll leave the inner ternarys as an exercise for the reader!

*PHP resolves nested ternary operators left to right rather than right to left. See http://php.net/manual/en/language.operators.comparison.php

1
Rimble On

I have no idea what each variable holds but this is a way to deconstruct it.

if($cust->is_company())
{
    echo 'TekCustomer__';
    if($cust->getID())
    {
        echo $cust->getID();
    }else
    {
        echo 'new'.$next_new_id-1;
    }
}else
{
    echo 'Person__';
    if($cust->people[0]->getID())
    {
        echo $cust->people[0]->getID();
    }else
    {
        echo 'new'.$next_new_id++;
    }
}
0
ForguesR On

You'll probably find it more readable like this :

$cust->is_company() ?
  'TekCustomer__' . ( $cust->getID() ? $cust->getID() : 'new'.($next_new_id-1) )
:
  'Person__' . ( $cust->people[0]->getID() ? $cust->people[0]->getID() : 'new'.$next_new_id++)

Basically it checks if it is a company :

  • Yes : it builds a string TekCustomer__ with the current ID of customer if it exists. If not it seems to generate a new id.
  • No : it builds a string Person__ with the current ID of a customer people if it exists. If not it seems to generate a new id.
0
Sal00m On
if ($cust->is_company())
    if ($cust->getID())
        return 'TekCustomer__' . $cust->getID();
    else
        return 'TekCustomer__new'.($next_new_id-1);
else
   if ($cust->people[0]->getID())
        return 'Person__' . $cust->people[0]->getID();
   else 
        return 'Person__new'.$next_new_id++);
0
Artur K. On

This is how it should probably be extended. It is called a ternary operator.

$statement ? value_if_true : value_if_false.

if($cust->is_company()) 
{
    $string = 'TekCustomer__';

    if($cust->getId()) 
    {
        $string .= $cust->getID();  
    } 
    else 
    {
        $string .= 'new'.($next_new_id-1));
    }
} 
else 
{
    $string = 'Person__';

    if($cust->people[0]->getID())
    {
        $string .= $cust->people[0]->getID();
    } 
    else 
    {
        $string .= 'new'.$next_new_id++;
    }
}
0
Isaac Hildebrandt On

It looks like this is a statement on the right hand side of an assignment. So, we would need to have a variable to build the string, and then just break it down by parentheses:

$tmp = '';
if ($cust->is_company()) { // first '?'
    $tmp .= 'TekCustomer__';
    if ($cust->getID()) { // second '?'
        $tmp .= $cust->getID();
    } else {
        $tmp .= 'new' . ($next_new_id - 1);
    } 
} else { 
    $tmp .= 'Person__'; 
    if ($cust->people[0]->getID()) { // third '?'
        $tmp .= $cust->people[0]->getID();
    } else { 
        $tmp .= 'new' . $next_new_id++;
    }
}