How can i merge multi arrays without using foreach

So here is a bit of tested working code using two data sets.

$users = array(
  array(
      "userid" => 1,
      "email" => "lewn@example.com",
      "phone" => 667790897
  ),
  array(
      "userid" => 2,
      "email" => "hen@example.com",
      "phone" => 4477905534
  )
);
// Keep things straight forward and just use foreach
// You can always use a fancier function later
$usersIndexedById = [];
foreach($users as $user) {
  $usersIndexedById[$user['userid']] = $user;
}

$metas = [
  ['metaid' => 1, 'userid' => 1, 'metakey' => 'city',    'metavalue' => 'Atlanta'],
  ['metaid' => 2, 'userid' => 1, 'metakey' => 'address', 'metavalue' => '9 road avenue'],
  ['metaid' => 3, 'userid' => 2, 'metakey' => 'city',    'metavalue' => 'Sheridan'],
  ['metaid' => 4, 'userid' => 1, 'metakey' => 'state',   'metavalue' => 'Georgia'],
  ['metaid' => 5, 'userid' => 2, 'metakey' => 'state',   'metavalue' => 'Wyoming'],
];
foreach($metas as $meta) {
  $userId = $meta['userid'];
  $usersIndexedById[$userId][$meta['metakey']] = $meta['metavalue'];
}
print_r($usersIndexedById);

Array
(
    [1] => Array
        (
            [userid] => 1
            [email] => lewn@example.com
            [phone] => 667790897
            [city] => Atlanta
            [address] => 9 road avenue
            [state] => Georgia
        )

    [2] => Array
        (
            [userid] => 2
            [email] => hen@example.com
            [phone] => 4477905534
            [city] => Sheridan
            [state] => Wyoming
        )

)

So that provides an answer to the original question.

1 Like

If you do a query like
SELECT * FROM users LEFT JOIN usersmeta ON users.userid = usersmeta.userid
Then your results should look something like
[userid = 42, email='bbb@mail.com', metakey='city', metavalue='Huntsvile'],

Pretty much the way sql/php work.

If you’re on MySQL 8, have you considered a JSON field for the user meta data?

That you way you can still query the one table, obtain all primary data and an additional key that contains all meta data as a JSON string. Run json_decode over it and you get an array.

The MySQL JSON type even allows to query within JSON fields.

What if a user has a metakey called age or school or anything else?

This is just a general design issue. What if questions can be very dangerous and can result in unnecessary code and slower development. What if users never us this meta capability? If you know for a fact that they will then sure. If not then design for what you do know.

You also need to think carefully about the rest of the meta implementation. Suppose the user does want an age property? Now what? How exactly are they going to do that? A user friendly interface for adding properties can be challenging. What will the rest of your application actually do with this custom property? Not to mention the fact that age is a number and not a string. Does that matter? Should you add a metatype to your table?

Lots and lots of stuff to consider.

That was a perfect answer thanks alot but if you read my initial you will notice i never wanted to loop the second time.
because i have already looped the usermeta separately to have it look like the way i posted it.

// rearrange usermeta
foreach($usermeta as $key => $value){
    $data[$value['userid']][$value['metakey'] = $value['value'];
}

return $data;

So this will sum all the user meta data into on single array.

Then i can actually use the $data array keys to merge it probably in the second foreach looping but I was looking for something handy instead of a second looping.

I am still nut sure what you want as a result but what about creating the meta data as a subarray of the user?

select u.userid, u.email, u.phone, 
          JSON_ARRAYAGG(select um.city, um.state, um.country from usersmeta um where um.userid = u.userid) as meta
from users

Sorry for using the word ā€œifā€

the original design structure allows for any new metakey for a given user

We are kind of going round and round here. Suffice it to say that with a minor tweak:

$usersIndexedById[$userId][$meta['metakey']] = $meta['metavalue'];

You can use your original dataset from the initial question. But I’ll leave that as an exercise for the reader.

The user can have many options to add to the metakey and we have limit the number of metakey keys that can be added but we don’t limit what the metakey is called.

example you have a limit of 100 rows to define yourself, so what ever you choose to call yourself must come as a single row or metakey with its value.

Everything has limit Sir

Yes your code for stripping the and arranging the metakey works.
Now lets not go into the usermeta the way it came.

Lets just stick with now we have a more better usermeta array and a user array ,how then do will merge both without looping or using foreach.

Any simple approach using array functions?

Thanks alot Sir, this answered my original question using the given data though a second foreach was used.

Now lets talk about the fancy functions that will replace this second looping here

So what was wrong with the code given to you in post 22? That does exactly what you want, without using any foreach.

Though I’m still not sure what’s wrong with using foreach, but okay.

Tired of being ignored here…

1 Like

Being noticed is overrated. Or so I have been told.

1 Like

So sorry Sir, you where not being ignored, just that you stayed focus on archiving it using SQL JOINS even though I am so eager to see such results but i noticed it can’t be archived that way because the metakey can be assumed to be dynamic and not fixed.

So hard coding the query has already limited the fun of having each user name their own metakey and then assign a value to it.

Note: we have a limit of 100 rows per user but the name of the metakey is solely dependant on the user.

That array_walk was beautiful i just noted it down as take one. but if i can have more samples i would be very :blush:

Why can’t you just do a simple LEFT JOIN and structure the results into a structured data array.
You manually define the 2 or 3 fields from the users table, i.e.

$userdata[$row['userid']]['userid']=$row['userid'];	 
$userdata[$row['userid']]['email']=$row['email'];	 
$userdata[$row['userid']]['phone']=$row['phone'];

Then results from the usermeta table use the key value pairs, i.e.

$userdata[$row['userid']][$row['metakey']]=$row['metavalue'];

This is a simple mysqli example.

$userdata = array();
$sql = "SELECT 
  u.userid
, u.email
, u.phone
, m.metakey
, m.metavalue 
FROM `users` u
	LEFT JOIN `usersmeta` m
		ON m.userid = u.userid";
$result = mysqli_query($db, $sql);
while($row = mysqli_fetch_assoc($result)){		 
	$userdata[$row['userid']]['userid']=$row['userid'];	 
	$userdata[$row['userid']]['email']=$row['email'];	 
	$userdata[$row['userid']]['phone']=$row['phone'];
	$userdata[$row['userid']][$row['metakey']]=$row['metavalue'];
}

Resulting in an array like this.

Array
(
    [1] => Array
        (
            [userid] => 1
            [email] => lewn@example.com
            [phone] => 667790897
            [city] => Georgia
            [address] => 9 road park avenue
            [country] => United States
            [state] => Georgia
            [gender] => Male
        )

    [2] => Array
        (
            [userid] => 2
            [email] => hen@example.com
            [phone] => 4477905534
            [state] => Wymoing
            [city] => Sheridan
            [country] => United States
            [age] => 35
        )

)

This topic was automatically closed 91 days after the last reply. New replies are no longer allowed.