1

I realize there are a number of questions about multidimensional arrays and foreach loops, and I have spent hours reading through them and trying to get my own loop to work -- without success. If the solution is a duplicate, I'll remove my question (or link to another if that is preferred).

Now, the challenge:

  • Using an array of returned MYSQL results. The results are from multiple joined tables in an associative array. Now I need to convert it to the multidimensional array I need.
  • I've got most of it working, but my issue is looping through and adding new items to the right place in the array.

Here's some code:

//example of how array is setup in the way I want, this part works.
foreach($results as $i => $a):

    //some other code is here, see below.

    $items[$i] = [
        "id" => $a['id'],
        "itemid" => $a['itemid'],
        "name" => $a['name'],
        "def" => $a['def'],
        "class" => $a['class'],
        "timeline" => $a['timeline'],
        "files" => [
            [0] => [
                "id" => $a['fileid'],
                "name" => $a['filename'],
                "path" => $a['filepath'],
                "type" => $a['filetype']
            ]
        ],
        "tags" => [
            [0] => [
                "id" => $a['tagid'],
                "name" => $a['tagname']
            ]
        ]
    ];
endforeach;

Then I've tried a number of ways to loop through in order to only add to the 'tags' or 'files' if the item 'id' is the same as the last. Here is the current code in my editor, not working:

//inside foreach loop, before above code
if($items[$i-1]['id'] == $a['id']):
    //it is the same item, works to here.
    if(in_array($a['filename'], $items[$i-1], FALSE)):
        //add to files array for last item
        $items[$i-1]['files'][] = [
            "id" => $a['fileid'],
            "name" => $a['filename'],
            "path" => $a['filepath'],
            "type" => $a['filetype']
        ];
    elseif(in_array($a['tagname'], $items[$i-1], FALSE)):
        //add to tags array for last item
        $items[$i-1]['tags'][] = [
            "id" => $a['tagid'],
            "name" => $a['tagname']
        ];
    endif;
else:// else it does the code above

As you can see, my most recent attempt was to use in_array, which I now realize doesn't work on multidimensional arrays. My issue is that I can't figure out how to determine if its a new file or new tag for the same item.

Ultimately, I want an array of 'items' which have multiple 'files' and 'tags.' I'm going to json_encode and use it with JS afterwards.

Any advice on how to get this working or optimize it, would be greatly appreciated.

P.S. As I mentioned above, I know this question has been asked before -- though I wasn't able to get their solutions working for me. I'll remove this question if the solution is a duplicate (as in, it's not really helpful to others). Thank you for any help, it is greatly appreciated!

2
  • What is your PHP version? On PHP >= 5.5 you can use array_column : in_array( $a['filename'], array_column( $items[$i-1]['files'], 'name' ) ) Commented Apr 11, 2016 at 14:13
  • Thanks for the tip @fusion3k. I'll read the docs on that function and give it a try. Commented Apr 11, 2016 at 14:16

1 Answer 1

0

Don't use "autoincrementing" array indices as they easily get messed up. Use your database id since it's already there:

//example of how array is setup in the way I want, this part works.
foreach($results as $i => $a):
$items[$a['id']] = [ // THIS CHANGED.
    "id" => $a['id'],
    "itemid" => $a['itemid'],
    ...

Now, with any further result, you can easily check, if the id is already in your array:

if (isset($items[$a['id']])) {
  // We had this id before, just add files/tags to it.
  // Check first, if files subarray exists, if not: create it.
  if (!isset($items[$a['id']]['files'])) {
    $items[$a['id']]['files'] = array();
  }
  $items[$a['id']]['files'][] = array(...); // add the new file.
  // Repeat for tags.
}

If your result could return the same file more than once for an id, you can check if the filename is already in there by using a search function:

$filename = $a['filename'];
if (!searchFilename($filename, $items[$a['id']]['files']) {
  // Filename is not in there, yet.
  // Add file info.
}

function searchFilename($id, $array) {
  foreach ($array as $key => $val) {
    if ($val['filename'] === $id) {
       return true;
    }
  }
  return false;
}

Same applies to tags in a similar way.

In the end, if you do not want the ids for index of $items, just call:

$items = array_values($items);
3
  • I think I understand where I went wrong now -- using the index. In the case there are more than 1 additional file/tag, it is looking at the wrong index in the array. Thank you for your explanation and time! I'm quite sure your solution will work for me. I'll confirm/mark solution once I get it in my code :P (P.S. Should I remove this question, or leave it? The flaw was in my logic =P Feel free to leave opinions as comments.) Commented Apr 11, 2016 at 14:26
  • Exactly, since $i is incremented regardless of $a['id'] was processed before or not. Commented Apr 11, 2016 at 14:28
  • I made a few alterations, but your solution was what I needed. I completely changed the way my array is setup, using the file/tag ids as their index. Thanks again Paul, you rock! Commented Apr 11, 2016 at 14:53

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.