26

How can I re-arrange a array of objects like this:

 [495] => stdClass Object
        (
         [date] => 2009-10-31 18:24:09
         ...
        )
 [582] => stdClass Object
        (
         [date] => 2010-2-11 12:01:42
         ...
        )
 ...

by the date key, oldest first ?

Nadine
  • 273
  • 1
  • 3
  • 4

6 Answers6

53
usort($array, function($a, $b) {
    return strtotime($a['date']) - strtotime($b['date']);
});

Or if you don't have PHP 5.3:

function cb($a, $b) {
    return strtotime($a['date']) - strtotime($b['date']);
}
usort($array, 'cb');
Arnaud Le Blanc
  • 98,321
  • 23
  • 206
  • 194
  • 3
    Looks good, and I'd recommend to the OP to do the date/time sorting in the database, and/or return a plain unix timestamp along with the formatted value, as strtotime() has CONSIDERABLE overhead and would make repeated sorting very expensive. – Marc B Aug 19 '11 at 21:50
  • 2
    replace `usort` by `uasort` then – Arnaud Le Blanc Aug 19 '11 at 22:06
24

Since the original question is about sorting arrays of stdClass() objects, here's the code which would work if $a and $b are objects:

usort($array, function($a, $b) {
    return strtotime($a->date) - strtotime($b->date);
});

Or if you don't have PHP 5.3:

function cb($a, $b) {
    return strtotime($a->date) - strtotime($b->date);
}
usort($array, 'cb');
MythThrazz
  • 1,629
  • 17
  • 25
4

I wanted to expand on arnaud576875's answer. I ran across this same issue, but with using DateTime objects. This is how I was able to accomplish the same thing.

usort($array, function($a, $b) {
    return $a['date']->format('U') - $b['date']->format('U');
});
Michael Irigoyen
  • 22,513
  • 17
  • 89
  • 131
  • Are you calling the `format()` method on a string value? This answer feels misleading to researchers. The OP's sample data is an array of objects, not an array of arrays. – mickmackusa Apr 15 '21 at 12:06
2

Because your month -- and possibly your day -- values are not zero-padded, you cannot instantly compare the dates as simple strings. You should use strtotime() to convert the dates to unix time integers -- these will be suitable for reliable comparisons.

Also, it seems important to not lose the associative relationship between the first level keys and their objects. To sort and retain the keys, call uasort(). In modern php, the spaceship operator is the go-to utility for making 3-way comparisons (returns -1, 0, or 1).

Code:

uasort(
    $array,
    function($a, $b) {
        return strtotime($a->date) <=> strtotime($b->date);
    }
);

Or in PHP7.4, there is arrow function syntax:

uasort(
    $array,
    fn($a, $b) => strtotime($a->date) <=> strtotime($b->date)
);

The only minor drawback with using function calls in u*sort()'s body is that it will do greater than n sets of function calls to break ties and otherwise determine the correct order. An alternative sorting technique that avoids these redundant function calls is array_multisort(). It can be fed a column of data which has had exactly n function calls performed -- this effectively makes it more efficient. However, this sorting function has its own caveat -- it will lose the numeric first level keys. This is probably not a tolerable loss for this case.

Code:

array_multisort(
    array_map('strtotime', array_column($array, 'date')),
    $array
);

Here is a demo of both techniques.

For anyone who is sorting date, time, or datetime values that can be naturally compared as basic strings (so-called Big-endian formats such as Y-m-d H:i:s, H:i, m/d, Y-m-d, etc., then see this answer for more efficient techniques.

mickmackusa
  • 43,625
  • 12
  • 83
  • 136
0

I wanted to expand on arnaud576875 and Michael Irigoyen.

Same issue with object containing dateTime with Symphony.

I coudn't use $a['date'] because it was not an key array.

usort($verifications, function($a, $b) {
   return $a->getDate()->format('U') - $b->getDate()->format('U');
});

This solved my problem

Naqued
  • 29
  • 7
0

When working with DateTime objects as properties of your Entity, this worked for me:

$myArray = $entityRepository->findAll();

usort($myArray, function($a, $b) {
    return $a->getDate()->getTimestamp() - $b->getDate()->getTimestamp();
        });
shjiemon
  • 21
  • 5
  • Your answer could be improved with additional supporting information. Please [edit] to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Dec 03 '21 at 23:34