Welcome to the Treehouse Community

Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.

Looking to learn something new?

Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.

Start your free trial

PHP

comparing arrays of objects

I have some PHP and SQL returning an array of objects or an array of users I am trying to compare groups of array objects. I am currently returning them and grouping them by email because I am looking for accounts that use the same email.

I need to check the groups coming back and compare with thing like

if all logins are blank find the user with most recent login_seen and set the rest emails to null.

or if not all login is null, find all that are null and set email to null

I can't seem to get this to work in a foreach loop because while in that loop I only ever have one object.

each user is laid out like such

{
  [user_account_nbr] => 1234,
  [email] => user@example.com,
  [login] => user,
  [last_seen] => 09-01-2015
},
{
  [user_account_nbr] => 12345,
  [email] => user@example.com,
  [login] => user2,
  [last_seen] => 08-31-2015
},
{
  [user_account_nbr] => 123456,
  [email] => user@example.com,
  [login] => ' ',
  [last_seen] => 08-30-2015
}

I've ran through all of Randy Hoyt and Hampton Paulk's courses to try to figure this out.

2 Answers

Codin - Codesmite
Codin - Codesmite
8,600 Points

This isn't the perfect answer to your question but this is a rough breakdown of how I would go about doing what you are trying. My arrays are fairly similiar in layout to your SQL database.. but even if it is not accurate the general ideas should work the same.. this isn't a copy and paste answer more of a guidline of ways you could go about doing the above.

<?php

$users = array(
    array(
        'user_account_nbr' => 1234,
        'email'=> 'user@example.com',
        'login' => 'user',
        'last_seen' => 2016
        ),
    array(
        'user_account_nbr' => 12345,
        'email'=> 'user@example.com',
        'login' => 'user2',
        'last_seen' => 2015
        ),
    array(
        'user_account_nbr' => 123456,
        'email'=> 'user@example.com',
        'login' => NULL,
        'last_seen' => 2014
        ),
    array(
        'user_account_nbr' => 1234567,
        'email'=> 'test@example.com',
        'login' => 'test',
        'last_seen' => 2013
        ),
    array(
        'user_account_nbr' => 12345678,
        'email'=> 'user@example.com',
        'login' => NULL,
        'last_seen' => 2012
        ),
    array(
        'user_account_nbr' => 123456789,
        'email'=> 'nologin@example.com',
        'login' => NULL,
        'last_seen' => 1998
        ),
    array(
        'user_account_nbr' => 12345678910,
        'email'=> 'nologin@example.com',
        'login' => NULL,
        'last_seen' => 1950
        )
    );
    $skip = array();                                            // Blank array to store checked entries so they can be skipped
    $haslogin = FALSE;                                          // Variable we will use later to check if an array of matching email users contains logins or if they are all null

for ($i = 0; $i <= (count($users)-1); $i++){                    // Loop through user array
    if (in_array("$i", $skip) == TRUE){                         // Check if current user has been already checked
                                                                // Do nothing as user has already been checked
    }
    else {                                                      // User not found in $skip array, continue with if statement
        $temp = array();                                        // Temporary array to store key values for users that share the same e-mail as the current user in the loop
        for ($x = 0; $x <= (count($users)-1); $x++){            // Loop back through the array, with this loop we are goign to check the emails to see if they match current selected user in the parent loop
            if ($users[$i]['email'] === $users[$x]['email']){   // Check if current user of child loop shares the same e-mail as the current user in the parent loop
                array_push($temp, $x);                          // Push the key of the user of the child loop to the $temp array
            };
        };
    foreach($temp as $value){                                   // Loop each user that has been added to the $temp array (These users all have matching emails to the currently selected user in the top parent loop)
        if ($users[$value]["login"] !== NULL){                  // Check if the user has a value for login.
            $haslogin = TRUE;                                   // If one of the users looped has a value for login, variable will be set to true.
        };
    };

    if ($haslogin == TRUE){                                     // If the last loop found that one or more of the users in the $temp array contain a value for login
        foreach($temp as $value){                               // Loop backthrough the $temp array
            if ($users[$value]["login"] == NULL){               // Check if the user does not have a value for login
                $users[$value]["email"] = NULL;                 // Set the email value of the user(s) with no value for login to NULL
            };
        };
    }
    else {                                                      // Else if haslogin returned FALSE
        $date = 0;                                              // Set variable for comparing last login date
        $latest = NULL;                                         // Set varaible for storing the key of the the user with the latest login.
        foreach($temp as $value){                               // Loop backthrough the $temp array
            if ($users[$value]["last_seen"] > $date){           // If current selected user last seen date greater then $date
                $date = $users[$value]["last_seen"];            // Set $date to the greater value of the current selected user
                $latest = $value;                               // Set latest to the key number of the current selected user
            };
        };
        foreach($temp as $value){                               // Loop backthrough the $temp array
            if ($value !== $latest){                            // If user is not the user with the most recent visit date
                $users[$value]["email"] = NULL;                 // Set the email value of the user(s) with not the latest visit date ot NULL
            };
        };

    };
foreach($temp as $value){                                       // Loop backthrough the $temp array
    array_push($skip, $value);                                  // Add the key values of the users we have just checked to the $skip array so that the main parent loop skips past them.
};
unset($temp);                                                   // Unset $temp array so it can be used on the next user in the main parent loop
$haslogin = FALSE;                                              // Set $haslogin back to FALSE so it is not already triggered on the next user in the main parent loop
};

};

print "<pre>";
print_r($users);                                    // Print User array to see changes
print "</pre>";

https://phpbox.info/f4eAc

Hope this helps ;)

If you need anything explained just let me know!

Holy wow man, I was expecting a one liner or a link to a manual. Thanks this gets me started pretty solidly I think. This whole ordeal exist because our programs older iterations didn't varify/validate, or sanitize inputs into the database.

This works great, I have a query pulling my duplicate emails now... pulling a distinct email form each set of duplicates. I just need to drop this in a foreach loop so it will run for each email that is returned in that array. then as the end foreach group execute sql to update the rows independently.

I am very close now.

I think there is a much better way of doing this if your data is in a database.

SELECT name, COUNT(email) FROM users GROUP BY email HAVING ( COUNT(email) > 1 )

For more discussion see this Stack Overflow thread.