1

I have a small issue I can't seem to figure out easily. The fix is probably quite easy but I am too much of a noob to fix it myself. Perhaps you guys could shed some light on this.

The issue

I need to create a multidimensional array in PHP. This works just fine. However, the last nested array sometimes consists of 2 elements, other times of 3. Hence "asymmetrical" in the title of this post.

The issue is most likely caused by the creation of the nested array based on the switch variables in my PHP code. When a variable is not defined ($button in case 'inactive' for example), the key is put inside the $elements array anyway but without a value.

The PHP code

$player = Array();
$data = @$_POST['players'];

if (!empty($data) && is_array($data)) {
    foreach($data as $id){

        $player_info = mysqli_query($connection, "SELECT * FROM players WHERE id = '$id'");
        $player_info = mysqli_fetch_assoc($player_info);

        switch ($player_info['status']) {
            case 'active':
                $color = '#30B490';
                $status = 'active';
                $button = 'buttons';
                break;
            case 'inactive':
                $color = '#A1A1A1';
                $status = 'inactive';
                break;
            case 'standby':
                $color = '#F0AD4E';
                $status = 'standby';
                $button = 'buttons';
                break;
            default:
                $color = '#4FA1D9';
                $status = 'unknown';
                break;
        }

        // THIS PART SEEMS TO CAUSE MY ISSUE
        $elements = array(
            "indicator" => $color,
            "status" => $status,
            "button" => $button
        );
        // THIS PART SEEMS TO CAUSE MY ISSUE

        foreach ($elements as $label => $element) {
            $player[$id][$label] = $element;
        }
    }
}

print_r($player);

print_r() results

Currently

Array (
    [1] => Array (
        [indicator] => #A1A1A1
        [status] => inactive
        [button] =>
    )
    [2] => Array (
        [indicator] => #30B490
        [status] => active
        [button] => yes
    )
    [3] => Array (
        [indicator] => #4FA1D9
        [status] => standby
        [button] => yes
    )
)

What it should be

Array (
    [1] => Array (
        [indicator] => #A1A1A1
        [status] => inactive
    )
    [2] => Array (
        [indicator] => #30B490
        [status] => active
        [button] => yes
    )
    [3] => Array (
        [indicator] => #4FA1D9
        [status] => standby
        [button] => yes
    )
)

You can see the difference between the 2 results. Look at [button] =>. When I json_encode() the entire multidimensional array the result shows a value null which just doesn't seem right.

{"1":{"indicator":"#A1A1A1","status":"inactive","button":null},"2":{"indicator":"#30B490","status":"active","button":"buttons"},"3":{"indicator":"#4FA1D9","status":"unknown","button":"buttons"}}

What I'd like

I would like the multidimensional array to be clean (without empty values) like shown in the "what is should be" print_r() result.

Any idea what I should edit in my PHP code in order to create a proper multidimensional array?

Best regards, Peter de Leeuw

3 Answers3

0

Yep this causes the issue

    // THIS PART SEEMS TO CAUSE MY ISSUE
    $elements = array(
        "indicator" => $color,
        "status" => $status,
        "button" => $button
    );

What happens is that your define the key button with an empty var $button also the next iteration $button isn't reset and your script could result in some unexpected behavior

Why not assign the $element like this?

    switch ($player_info['status']) {
        case 'active':
            $elements = array(
            'color' => '#30B490',
            'status' => 'active',
            'button' => 'buttons');
            break;
        case 'inactive':
            $elements = array(
            'color' = '#A1A1A1',
            'status' = 'inactive');
            break;
        case 'standby':
            $elements = array(
            'color' => '#F0AD4E',
            'status'  => 'standby',
            'button' => 'buttons');
            break;
        default:
            $elements = array(
              'color' => '#4FA1D9';
              'status' => 'unknown');
            break;
    }

Or even like this:

    $player[$id]['status'] = $player_info['status'];
    switch ($player_info['status']) {
        case 'active':
            $player[$id]['color'] = '#30B490';
            $player[$id]['button'] = 'buttons';
            break;
        case 'inactive':
            $player[$id]['color'] = '#A1A1A1';
            break;
        case 'standby':
            $player[$id]['color'] = '#F0AD4E';
            $player[$id]['button'] = 'buttons';
            break;
        default:
            $player[$id]['color'] = '#F0AD4E';
            $player[$id]['status'] = 'unknown'; //overwrite status from database to unknown
            break;
    }

Or smaller

//Outside the loop
$colors = array('active' =>'#30B490', 'inactive' => '#A1A1A1', 'standby' => '#F0AD4E');

//Inside the loop
$player[$id]['status'] = $player_info['status'];
$player[$id]['color'] = isset($colors[$player_info['status']) ? $colors[$player_info['status'] : '#4Fa1D9'; 
if($player[$id]['status'] == 'active' || $player[$id]['status'] == 'standby') 
    $player[$id]['buttons'] = 'buttons';
Sander Visser
  • 4,144
  • 1
  • 31
  • 42
  • Any idea how I could "dynamically" decide for each `$id` what the size of the next array should be? (2 or 3 keys). Indeed, now I create a 3 key nested array for every `$id`, even though some cases only need 2 keys in a nested array. * I just noticed you edited your post, I'll check it out. –  Sep 17 '14 at 09:57
  • Your first edit seemed to have worked! The arrays are clean now, no empty values; exactly how the `print_r()` result should look like. I will try the other approach as well since. –  Sep 17 '14 at 10:12
  • Made your script 10 times smaller ;) – Sander Visser Sep 17 '14 at 10:16
0

Why don't you just assign a "no" value to $button instead?

switch ($player_info['status']) {
    case 'active':
        $element = array(
        'color' => '#30B490',
        'status' => 'active',
        'button' => 'buttons');
        break;
    case 'inactive':
        $element = array(
        'color' = '#A1A1A1',
        'status' = 'inactive');
        'button' => 'no');
        break;
    case 'standby':
        $element = array(
        'color' => '#F0AD4E',
        'status'  => 'standby',
        'button' => 'buttons');
        break;
    default:
        $element = array(
          'color' => '#4FA1D9';
          'status' => 'unknown');
        break;
}

This should help you process your answer later with json.parse

John Doeff
  • 309
  • 3
  • 7
  • I could do it this way but I prefer to learn a better approach how to create asymmetrical multidimensional arrays. The button yes/no was only used as a case for my issue. The real implementation is different. –  Sep 17 '14 at 10:06
  • If your output is json in your real implementation, then "assymetrical" arrays are just a bad idea anyway. – John Doeff Sep 17 '14 at 10:10
  • Could you explain why "asymmetrical" arrays are a bad idea if I `json_encode()` it later on? –  Sep 17 '14 at 10:14
  • Parsing json is looping thru key:value and having the same index count in each loop is mandatory. ( well, you can add conditionals on the other side to re-create a null value for the missing button, but why removing it in the first place? )" – John Doeff Sep 17 '14 at 10:18
-1

You could simply use array_filter()

$player = array_map('array_filter', $player);

This will clean empty values of every array in $player

Ram Sharma
  • 8,676
  • 7
  • 43
  • 56
pistou
  • 2,799
  • 5
  • 33
  • 60