PHP Array: Twice if statement in a for

312 views Asked by At

I'm having a difficult to finish a if statement twice.. The rest works fine but when I try to check in another subarray it doesn't work.

EDIT: - The first if condition is to check the type of products - The second if condition is to check the size attributes. - Products: sweatshirt_crianca and sweatshirtc_crianca_capuz - Sizes: 4_anos, 6_anos, 8_anos, 11_anos, 12_anos and 14_anos Need to disable ( $this->enabled = false; ) Those sizes except 14_anos.

This is what I get from $order->products[$i]

Array
(
    [qty] => 1
    [name] => .Mr Mickey T-shirt
    [model] => 
    [image] => blusa-mr-mrs-blusao-sweat-camisolas-portugal.png
    [tax] => 20
    [tax_description] => IVA 23%
    [price] => 10.8333
    [final_price] => 16.6666
    [weight] => 0.00
    [id] => 1342{18}135{17}132{19}148
    [attributes] => Array
        (
            [0] => Array
                (
                    [option] => s_cor_produto
                    [value] => branco
                    [option_id] => 18
                    [value_id] => 135
                    [prefix] => +
                    [price] => 0.0000
                )

            [1] => Array
                (
                    [option] => s_produto
                    [value] => sweatshirt_crianca
                    [option_id] => 17
                    [value_id] => 132
                    [prefix] => +
                    [price] => 5.8333
                )

            [2] => Array
                (
                    [option] => s_tamanho_produto
                    [value] => 8_anos
                    [option_id] => 19
                    [value_id] => 148
                    [prefix] => +
                    [price] => 0.0000
                )

        )

)
Array
(
    [qty] => 1
    [name] => Adivinha quem vai ser mama shirt
    [model] => 
    [image] => adivinha-quem-vai-ser-mama-tshirt-gravida.png
    [tax] => 20
    [tax_description] => IVA 23%
    [price] => 10.8333
    [final_price] => 10.8333
    [weight] => 0.00
    [id] => 1860{20}157{18}139{17}128{19}152
    [attributes] => Array
        (
            [0] => Array
                (
                    [option] => s_cor_impressao
                    [value] => branco
                    [option_id] => 20
                    [value_id] => 157
                    [prefix] => +
                    [price] => 0.0000
                )

            [1] => Array
                (
                    [option] => s_cor_produto
                    [value] => azul_royal
                    [option_id] => 18
                    [value_id] => 139
                    [prefix] => +
                    [price] => 0.0000
                )

            [2] => Array
                (
                    [option] => s_produto
                    [value] => tshirt_mulher
                    [option_id] => 17
                    [value_id] => 128
                    [prefix] => +
                    [price] => 0.0000
                )

            [3] => Array
                (
                    [option] => s_tamanho_produto
                    [value] => M
                    [option_id] => 19
                    [value_id] => 152
                    [prefix] => +
                    [price] => 0.0000
                )

        )

)

Sometimes it can contains 1 or 4 subarrays. This is cod payment from osCommerce, I'm trying to exclude specific products from this method based on the attributes of it. This works fine in the first if statement to check the [value] but the lines that are commented the syntax is correct but it's not working. This is the code I got:

  for ($i=0, $n=sizeof($order->products); $i<$n; $i++) {
    if ($order->products[$i]['weight'] > '0.00') {
      $this->enabled = false;
    }
    if ( (isset($order->products[$i]['attributes'])) && (sizeof($order->products[$i]['attributes']) > 0) ) {
      for ($j=0, $n2=sizeof($order->products[$i]['attributes']); $j<$n2; $j++) {
        if ( ($order->products[$i]['attributes'][$j]['option'] == 's_produto') && ($order->products[$i]['attributes'][$j]['value'] == 'sweatshirt_crianca') ) {
          //if ( ($order->products[$i]['attributes'][$j]['option'] == 's_tamanho_produto') && ($order->products[$i]['attributes'][$j]['value'] == '14_anos') ) {
            $this->enabled = false;
          //}
        }
        else if ( ($order->products[$i]['attributes'][$j]['option'] == 's_produto') && ($order->products[$i]['attributes'][$j]['value'] == 'sweatshirtc_crianca_capuz') ) {
          //if ( ($order->products[$i]['attributes'][$j]['option'] == 's_tamanho_produto') && ($order->products[$i]['attributes'][$j]['value'] != '14_anos') ) {
            $this->enabled = false;
          //}
        }
      }
    }
  }

Any solutions? Thanks.

3

There are 3 answers

1
datascript On

Sidyll beat me to it but I was thinking along similar lines:

  // loop through each product
  foreach ( $order->products as $prod )
  {

        if($prod['weight'] > '0.00')
        {
                $this->enabled = false;
        }

        if( isset($prod['attributes']) && is_array($prod['attributes']) )
        {
                $matching_product_type_found = false;
                $matching_valid_size_found = false;

                foreach ( $prod['attributes'] as $attr )
                 {
                       if ( $attr['option'] == 's_produto' &&
                            ( $attr['value'] == 'sweatshirt_crianca' ||
                              $attr['value'] == 'sweatshirtc_crianca_capuz'
                            ) )
                          {
                            $matching_product_type_found = true;
                          }

                       if ( $attr['option'] == 's_tamanho_produto' && $attr['value'] == '14_anos' )
                          {
                            $matching_valid_size_found = true;
                          }
                 }


                if( $matching_product_type_found == true )
                {

                     $this->enabled = $matching_valid_size_found;

                }

        }

  }
1
CodeGodie On

I would rewrite your loop using foreach to make it more readable and prone to less errors. Also, watch out for your comparisons (== vs. ===). Try it in this manner:

foreach ($order->products as $product) {
    if ($product['weight'] > 0.00) {
        $this->enabled = false;
    }
    if (!empty($product['attributes'])) {
        foreach ($product['attributes'] as $attribute) {

            if ($attribute['option'] === 's_produto') {

                switch ($attribute['value']) {
                    case "sweatshirt_crianca" :
                        // .. do some code
                        break;
                    case "s_tamanho_produto" :
                        // .. do some code
                        break;
                    case "14_anos" :
                        // .. do some code
                        break;
                    case "something else" :
                        // .. do some code
                        break;
                    default:
                        break;
                }

            }
        }
    }
}
0
sidyll On

The main problem with your code is that you want to test for different array elements but you're doing it while iterating one by one. The code inside the for loop will only see the current element on the iteration. So when you nest the if statements, you're basically testing if the current element is equal to something, and then if it is you test if this very same element is equal to something else. This logic will fail.

Since apparently only the option and value keys are important, I suggest creating another array with those first. Then, you can access all these properties at once -- and not only the current attribute inside an iterator. For example, here is a simplified attributes array for your last example in the question:

$attributes = [
    s_cor_impressao   => 'branco'
    s_cor_produto     => 'azul_royal'
    s_produto         => 'tshirt_mulher'
    s_tamanho_produto => 'M'
];

To create this easily and also to simplify your code, I suggest using the foreach ... as loop. Also, you don't need to check if the array has items. If there are no items, simply the foreach won't be executed at all. It is worth checking if it is set, like you did, if you don't know in advance. But another way is to just skip directly to the next iteration if it is not set with the continue control structure.

foreach ($order->products as $product) {
    if ($product['weight'] > 0)
        $this->enabled = false;

    if (!isset($product['attributes']) || !is_array($product['attributes']))
        continue;

    $attributes = [];
    foreach ($products['attributes'] as $attr)
        $attributes[ $attr['option'] ] = $attr['value'];

    # [tests]
}

Now, in the tests mark above you can do your tests like:

if ($attr['s_produto'] == 'sweatshirt_crianca' &&
    $attr['s_tamanho_produto'] == '14_anos') {
    # do something
    # $this->enabled = false;
} else if (...) {
    # do something else
}