PHP Sorting Problem

DarkLight's picture

He has: 287 posts

Joined: Oct 2007

Hey guys, it's good to be back!
I have a small problem with a code I wrote... I need to sort the output by the $days string (ascending) so once printed, will display with the smallest number to the top.

<?php
$result
= db_query("SELECT uid FROM {users}");
while (
$uid = db_fetch_object($result)) {
 
$uids[] = user_load($uid->uid);
}
foreach(
$uids as $data) {
$days = ($data->profile_details_birthdate['day']) - date("d");
$months = ($data->profile_details_birthdate['month']) - date("m");
if(
$months == "0" && $days <= "7") {
if(
$days > "0") {
print
l($data->name,'user/'.$data->uid).'\'s birthday in '.format_plural($days, '1 day', '@count days').'<br />';
}
if(
$days == "0") {
print
'<strong>'.l($data->name,'user/'.$data->uid).'\'s birthday is today!</strong>';
print
' (<a class="formdialog" href="/messages/new/'.$data->uid.'/Happy%20Birthday,%20'.$data->name.'!">Send Message</a>)<br />';
}
}
}
?>

Can anyone point me in the right direction?

Thanks! Smiling

All the best news here: https://newsbotnet.com

Greg K's picture

He has: 2,145 posts

Joined: Nov 2003

This first version is if you need to have all the users in an array for some other reason besides just the birthday list. Please note the use of mktime to make sure time stamps are at midnight, and that they will be the correct values for leap years and for wrapping the end of the year till the next. Your code was only checking if the birthday was within the same month. What it if is May 29, a birthday on June 1 wouldn't list.

<?php
    $aryBDkeys
= array();
   
$aryUIDs = array();

   
$result = db_query("SELECT uid FROM {users}");   // Add an ORDER BY for any secondary sort after Days

    // Load this into an array to lessen the number of calls
   
$intYear = date('Y');
   
$tsTodayMidnight = mktime(0,0,0,date('m'),date('d'),date('Y'));
   
$int24Hours = 24*60*60;
   
$ts7Days = $tsTodayMidnight + (7*$int24Hours);
   
$intRecCount = 0;

    while (
$uid = db_fetch_object($result)) {
       
$aryUIDs[$intRecCount] = user_load($uid->uid);
       
$tsBD = mktime(0,0,0,$aryUIDs[$intRecCount]->profile_details_birthdate['month'],$aryUIDs[$intRecCount]->profile_details_birthdate['day'],$intYear);
        if (
$tsBD < $tsTodayMidnight) {
           
// Birthday this calendar year already passed, so change to next calendar year
           
$tsBD = mktime(0,0,0,$aryUIDs[$intRecCount]->profile_details_birthdate['month'],$aryUIDs[$intRecCount]->profile_details_birthdate['day'],$intYear+1);
        }
        if (
$tsBD <= $ts7Days) {
           
// it is between today and 7 days...
           
$aryBDkeys[$intRecCount] = ($tsBD - $tsTodayMidnight) / $int24Hours;
        }
    }

   
asort($aryBDkeys);

    foreach(
$aryBDkeys as $intUIDkey=>$intDays) {
        if(
$intDays > "0") {
            print
l($aryUIDs[$intUIDkey]->name,'user/'.$aryUIDs[$intUIDkey]->uid).'\'s birthday in '.format_plural($days, '1 day', '@count days').'<br />';
        }
        else {
            print
'<strong>'.l($aryUIDs[$intUIDkey]->name,'user/'.$aryUIDs[$intUIDkey]->uid).'\'s birthday is today!</strong>';
            print
' (<a class="formdialog" href="/messages/new/'.$aryUIDs[$intUIDkey]->uid.'/Happy%20Birthday,%20'.$aryUIDs[$intUIDkey]->name.'!">Send Message</a>)<br />';
        }
    }
    unset(
$aryBDkeys );
?>

ok, now a version for if you are just getting the records for the list of the birthdays:

<?php
    $aryUIDs
= array();

   
$result = db_query("SELECT uid FROM {users}");   // Add an ORDER BY for any secondary sort after Days

    // Load this into an array to lessen the number of calls
   
$intYear = date('Y');
   
$tsTodayMidnight = mktime(0,0,0,date('m'),date('d'),date('Y'));
   
$int24Hours = 24*60*60;
   
$ts7Days = $tsTodayMidnight + (7*$int24Hours);
   
$intRecCount = 10000; // This will work up to 90,000 records

   
while ($uid = db_fetch_object($result)) {
       
$aryTemp = user_load($uid->uid);
       
$tsBD = mktime(0,0,0,$aryTemp->profile_details_birthdate['month'],$aryTemp->profile_details_birthdate['day'],$intYear);
        if (
$tsBD < $tsTodayMidnight) {
           
// Birthday this calendar year already passed, so change to next calendar year
           
$tsBD = mktime(0,0,0,$aryTemp->profile_details_birthdate['month'],$aryTemp->profile_details_birthdate['day'],$intYear+1);
        }
        if (
$tsBD <= $ts7Days) {
           
// it is between today and 7 days...
           
$aryTemp['DaysToBD'] = ($tsBD - $tsTodayMidnight) / $int24Hours;
           
$aryUIDs[$aryTemp['DaysToBD'].($intRecCount++)] = $aryTemp; // use rec cound to make sure key unique
       
}
    }

   
ksort($aryUIDs);

    foreach(
$aryUIDs as $aryData) {
        if(
$aryData['DaysToBD'] > "0") {
            print
l($aryData->name,'user/'.$aryData->uid).'\'s birthday in '.format_plural($aryData['DaysToBD'], '1 day', '@count days').'<br />';
        }
        else {
            print
'<strong>'.l($aryData->name,'user/'.$aryData->uid).'\'s birthday is today!</strong>';
            print
' (<a class="formdialog" href="/messages/new/'.$aryData->uid.'/Happy%20Birthday,%20'.$aryData->name.'!">Send Message</a>)<br />';
        }
    }
    unset(
$aryUIDs);
?>

However to be honest, if you are jsut listing the next 7 days worth, it is better find a way to just return it from the SQL query.

-Greg

DarkLight's picture

He has: 287 posts

Joined: Oct 2007

Hey greg, thanks for the response. The code is great! And you alerted me to that issue with the same month check... I am having problems with both codes... The first, returns only one user... I'm guessing I have to loop it somewhere, but how? The second, returns a PHP Error. I remove the semicolon from the } and the page loads properly, but it screws up the content.

I'm no expert here, but I'm willing to learn Smiling

Thanks again.

All the best news here: https://newsbotnet.com

DarkLight's picture

He has: 287 posts

Joined: Oct 2007

Hey, I appreciate your help, but I've decided to use the Birthday module for Drupal. It's more efficient and does exactly what I need. Plus it is easily themed. Smiling

All the best news here: https://newsbotnet.com

Greg K's picture

He has: 2,145 posts

Joined: Nov 2003

Ahh, on the first one I forgot to put in the $intRecCount++; inside the while loop.

Even though you went with another method, where did you remove the ; from ont he second one?

DarkLight's picture

He has: 287 posts

Joined: Oct 2007

Hey Greg... Sorry about that, I was wrong, my eyes are a pain in the backside... It wasn't a } it was a ) Laughing out loud
*embarassed* Now I feel stupid Laughing out loud

Want to join the discussion? Create an account or log in if you already have one. Joining is fast, free and painless! We’ll even whisk you back here when you’ve finished.