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) "kkkk@gggg.com"
    ["firstname"]=>
    string(8) "aaaaa"
    ["lastname"]=>
    string(12) "bbbbb"

  }
  [1]=>
  array(4) {
    ["id"]=>
    string(1) "102"
    ["email"]=>
    string(17) "mmmmm@hhhhh.com"
    ["firstname"]=>
    string(12) "vvvv"
    ["lastname"]=>
    string(12) "zzzzz"

  }
  [2]=>
  array(4) {
    ["id"]=>
    string(2) "103"
    ["email"]=>
    string(17) "eeee@gmail.com"
    ["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

DaveRandom
  • 87,921
  • 11
  • 154
  • 174
Leron
  • 9,546
  • 35
  • 156
  • 257

4 Answers4

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.

Community
  • 1
  • 1
Squig
  • 862
  • 6
  • 15
  • 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? – Leron Mar 30 '12 at 16:41
  • 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... – Squig Mar 30 '12 at 17:09
  • 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... – Squig Mar 30 '12 at 17:15
  • 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. – Leron Mar 30 '12 at 18:59
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
)
*/
nyson
  • 1,055
  • 6
  • 20
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);
DaveRandom
  • 87,921
  • 11
  • 154
  • 174
  • 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 Mar 30 '12 at 14:47
  • @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](http://codepad.viper-7.com/j8TELT). – DaveRandom Mar 30 '12 at 15:10
  • Thanks I want to look further into it for sure! – Leron Mar 30 '12 at 16:09
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

Cfreak
  • 19,191
  • 6
  • 49
  • 60