1

I have one main array which is the returned data from a MySQL query for user table which looks like this :

array(36) {
  [0]=>
  array(4) {
    ["id"]=>
    string(1) "101"
    ["email"]=>
    string(15) "[email protected]"
    ["firstname"]=>
    string(8) "aaaaa"
    ["lastname"]=>
    string(12) "bbbbb"

  }
  [1]=>
  array(4) {
    ["id"]=>
    string(1) "102"
    ["email"]=>
    string(17) "[email protected]"
    ["firstname"]=>
    string(12) "vvvv"
    ["lastname"]=>
    string(12) "zzzzz"

  }
  [2]=>
  array(4) {
    ["id"]=>
    string(2) "103"
    ["email"]=>
    string(17) "[email protected]"
    ["firstname"]=>
    string(6) "ggggg"
    ["lastname"]=>
    string(12) "zzzzz"

And so on... And a second array which is again MySQL query which is from a table with two foreign keys making relation b/w two table many to many and looks like this:

array(7) {
  [0]=>
  array(2) {
    ["user_id"]=>
    string(3) "101"
    ["group_id"]=>
    string(1) "1"
  }
  [1]=>
  array(2) {
    ["user_id"]=>
    string(3) "102"
    ["group_id"]=>
    string(1) "1"
  }
  [2]=>
  array(2) {
    ["user_id"]=>
    string(3) "103"
    ["group_id"]=>
    string(1) "1"
  }

The final goal is to make a 5th key in the first array, something like:

["groups"]=>...

which i can populate with the id's of the groups which every user takes part in and at the end to look like something like this:

["groups"]=>"1,2,3,4"

In other words, because the relation is many to many the user may participate in more than one group when I push the new value I don't want to create a new key with value but instead to concatinate the existing values of the key with the new id.

So far I got something like this:

$query = $this->mUsers->getAll(); //Main query to get users data
          $results = $this->mUsers->getGroupsAndUsers(); //Query for getting the group_id and user_id
        //  Looping both arrays to find matching ID's

          foreach($query as $key=>$value){ //$value['id'] returns the value of the users id from table users
              foreach($results as $row){
                  if ($value['id']==$row['user_id'])
               {
                          array_push($value,"groups",$row['group_id']);

                }

              } 

}

But I doesn't work. I tried a few other things but nothing by now.

Thanks Leron

4 Answers 4

2

You may be better off doing the heavy lifting in SQL, rather than in PHP.

So, if your users table is like this:

enter image description here

... your groups table is like this:

enter image description here

... and your users_groups table is like this:

enter image description here

... then you could use the following query:

SELECT id,email,firstname,lastname, GROUP_CONCAT(users_groups.group_id) as groups
FROM `users`
JOIN users_groups on users.id = users_groups.user_id
GROUP BY users.id;

(or this one, if you're testing in phpMyAdmin)

SELECT id,email,firstname,lastname, GROUP_CONCAT(CAST(users_groups.group_id AS CHAR)) as groups
FROM `users`
JOIN users_groups on users.id = users_groups.user_id
GROUP BY users.id;

... to produce this output:

enter image description here

Credit to this post for the info on how to produce comma-separated values from SQL, and the comment about using CAST AS CHAR.

Sign up to request clarification or add additional context in comments.

4 Comments

Hey, if you still follow this. This one is very nice but as it is, it only fetch the rows where groups column is not empty. Is there a way to list all the users no matter i they are in a group or not?
That should be one of the settings of the 'join' in the SQL. Let me check and I'll update my post with my findings...
If you replace "JOIN" with "LEFT JOIN" then that will include all users. If a user isn't in any groups then you'll get NULL in the groups column. Hope that helps. Happy to update my original post with the LEFT JOIN if necessary...
Yes, ty. I tried with IFNULL and LEFT JOIN and it works, gonna try asap only with LEFT JOIN, hopefully it gonna works this way too. Very useful post though. Thanks.
1

It's making your life more difficult, and making the data less useful, to try and construct a comma separated string. It makes much more sense to create a sub-array of values, which you can implode(',', $arr) if you need a string representation down the line. It also makes the job a lot easier, and the data more useable, if your array of user data has the same keys as the user_id field:

// First, get the array of users and format it with sensible keys
$users = array();
foreach ($this->mUsers->getAll() as $user) $users[$user['id']] = array_merge($user, array('groups' => array()));

// Now assign group relationships
foreach ($this->mUsers->getGroupsAndUsers() as $group) {
  $users[$group['user_id']]['groups'][] = $group['group_id'];
}

print_r($users);

3 Comments

This is the closest to what I need, however the hardest for me to understand by now. And with one simple issue, I get:["groups"]=> array(0) {, but I need a String instead, can it be changed, because I need time to read through your example ?
@Leron Sure, just loop the data one more time at the end and implode() it: foreach ($users as &$user) $user['groups'] = implode(',', $user['groups']);. I have made a small fix to the code above by the way, it wasn't quite right. If you want to have a play with it, have a look here.
Thanks I want to look further into it for sure!
1

As now, you're passing a cloned value and not a reference into the foreach. If you run a foreach($array as $value), $value is a copy. You have to run it as foreach($array as &$value) to actually edit $value. & means you are passing the argument as a reference instead of just cloning it.

Let me demonstrate with a simple example.

$names = array("bob", "joe", "mustafa", "ghandi");
foreach($names as $name) {
    $name = "name: " . $name; 
}
print_r($names);
/** prints:
Array
(
    [0] => bob
    [1] => joe
    [2] => mustafa
    [3] => ghandi
)
*/


$names = array("bob", "joe", "mustafa", "ghandi");
foreach($names as &$name) {
    $name = "name: " . $name; 
}
print_r($names);
/** prints:
Array
(
    [0] => name: bob
    [1] => name: joe
    [2] => name: mustafa
    [3] => name: ghandi
)
*/

1 Comment

Yeah, but the problem is that it should be - [0]=>name: bob, Joe, Mustafa
0

You're close!

Try:

foreach($query as $key=>$value ) {
    foreach($results as $row) {
        if( $value['id'] == $row['user_id'] ) {
            $query[$key]['groups'][] = $row['group_id'];
        }
    }
}   

The empty bracket [] appends to the array

1 Comment

I tried this way because it's closer to my approach but it don't work as it is :(

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.