Search code examples
phplaravelternary-operator

Ternary Operator with multiple conditions used inside an Array in PHP


If An API gives the following response, taking into consideration array[0] and array[1] sometimes can be value MX and sometimes can be value AR:

["published_sites"]=>
array(3) {
  [0]=>
  object(stdClass)#1565 (5) {
    ["site"]=>
    string(2) "MX"
    ["sale_price"]=>
    int(956)
    ["status"]=>
    string(6) "active"
    ["item_id"]=>
    string(12) "MLM724808"
    ["url"]=>
    string(108) "http://articulo.mercadolibre.com.mx/MLM-722808-apple-apple-watch-series-4-gps-cellular-44mm-space-bla-_JM"
  }
  [1]=>
  object(stdClass)#1569 (3) {
    ["site"]=>
    string(2) "AR"
        ["sale_price"]=>
        int(956)
        ["status"]=>
        string(6) "active"
        ["item_id"]=>
        string(12) "MLM724808"
        ["url"]=>
        string(108) "http://articulo.mercadolibre.com.ar/MLM-722808-apple-apple-watch-series-4-gps-cellular-44mm-space-bla-_JM"
}

and to save on Database you create an array with the following fields to assign values for AR and for MX:

    Channels::updateOrCreate(['mpid' => $response->mpid], [
    'mpid' => $response->mpid,
    'published_site_ar_item_id' => $assign item_id for AR, eg: $item_ar_assign
    'published_site_mx_item_id' => $assign item_id for MX,

Taking into consideration Array only can use ternary operator for conditionals I tried with the following structure, but using Or for multiple conditions didnt work. ->

item_ar_assign = ($response->published_sites['0']->site == 'AR' ?: $response->published_sites['0']->item_id)
                ||($response->published_sites['1']->site == 'AR' ?: $response->published_sites['1']->item_id)
            ||($response->published_sites['2']->site == 'AR' ? : $response->published_sites['2']->item_id)

is this approach of ternary operator + multiple conditions possible with arrays?

(note: I read SO for duplicates like Ternary operator with multiple conditions but I dont think is the same approach.)


Solution

  • Firstly, I'm not sure why you think there's a particular problem with arrays here. Let's substitute variables so that we can see the important part of the code:

    $site0 = $response->published_sites['0']->site;
    $id0 = $response->published_sites['0']->item_id;
    
    $site1 = $response->published_sites['1']->site;
    $id1 = $response->published_sites['1']->item_id;
    
    $site2 = $response->published_sites['2']->site;
    $id2 = $response->published_sites['2']->item_id;
    
    $item_ar_assign = 
        ($site0 == 'AR' ?: $id0)
        || ($site1 == 'AR' ?: $id1)
        || ($site2 == 'AR' ? : $id2);
    

    The reason this won't work has nothing to do with arrays, but because you have used the wrong operators:

    • PHP's || operator always returns a boolean - true or false, regardless of what values it looks at.
    • The form $a ?: $b means "$a if it is truthy, or $b if not". In this case, $site0 == 'AR' ?: $id0 would mean "true if $site0 is 'AR', or the value of $id0 if not"

    What I think you are trying to do is nest the full form of the ternary operator, $test ? $valueIfTrue : $valueIfFalse.

    Beware that the associativity is a bit odd, so you need to use parentheses carefully. I think this should work:

    $item_ar_assign =
        ($site0 == 'AR') ? $id0
        : (
            $site1 == 'AR' ? $id1
            : (
                $site2 == 'AR' ? : $id2
            )
        );
    

    Once you put your full variables back in, it's probably going to look better with full if statements.

    if ($response->published_sites[0]->site == 'AR' ) {
        $item_ar_assign = $response->published_sites[0]->item_id;
    }
    elseif ($response->published_sites[1]->site == 'AR' ) {
        $item_ar_assign = $response->published_sites[1]->item_id;
    }
    elseif ($response->published_sites[2]->site == 'AR' ) {
        $item_ar_assign = $response->published_sites[2]->item_id;
    }
    

    However, rather than copy-and-pasting the condition, you could put it in a loop:

    foreach ( [0, 1, 2] as $site_number ) {
        if ($response->published_sites[$site_number]->site == 'AR' ) {
            $item_ar_assign = $response->published_sites[$site_number]->item_id;
            break; // stop at first match
        }
    }
    

    Or even simpler:

    foreach ( $response->published_sites as $published_site ) {
        if ($published_site->site == 'AR' ) {
            $item_ar_assign = $published_site->item_id;
            break; // stop at first match
        }
    }