phparraysarray-multisort

Sort the first and second level of a 3d array by date column values in the third level


Not sure if this was asked before but can anyone help me sort below array by date (latest_user_activity_date). I was trying to search on the internet but I failed to sort this. I have tried using array_multisort function but it only sort the first index (admin). I am using PHP 5.3 version.

Array
  (
  [admin] => Array
    (
    [0] => Array
      (
      [id] => 3
      [user_type] => Accountant
      [latest_user_activity_date] => 2000 - 00 - 00 00: 00: 00
      [full_link] => admin / billing_contacts.app
      )
    [1] => Array
      (
      [id] => 1
      [user_type] => Accountant
      [latest_user_activity_date] => 2018 - 04 - 19 13: 18: 59.112704
      [full_link] => admin / billing_contacts.app
      )
    [2] => Array
      (
      [id] => 2
      [user_type] => Accountant
      [latest_user_activity_date] => 2018 - 04 - 15 13: 18: 59.112704
      [full_link] => admin / client_upload.app
      )
    )
  [invoice] => Array
    (
    [0] => Array
      (
      [id] => 3
      [user_type] => Accountant
      [latest_user_activity_date] => 2000 - 00 - 00 00: 00: 00
      [full_link] => admin / create_invoice.app
      )
    [1] => Array
      (
      [id] => 1
      [user_type] => Accountant
      [latest_user_activity_date] => 2018 - 04 - 19 13: 18: 59.112704
      [full_link] => admin / list_invoice.app
      )
    [2] => Array
      (
      [id] => 2
      [user_type] => Accountant
      [latest_user_activity_date] => 2018 - 04 - 20 13: 18: 59.112704
      [full_link] => admin / delete_invoice.app
      )
    )

  )

Desired output:

Array
(
    [invoice] => Array
        (
            [8] => Array
                (
                    [id] => 2
                    [user_type] => Accountant
                    [latest_user_activity_date] => 2018-04-20 13:18:59.112704
                    [full_link] => admin/delete_invoice.app
                )
            [7] => Array
                (
                    [id] => 1
                    [user_type] => Accountant
                    [latest_user_activity_date] => 2018-04-19 13:18:59.112704
                    [full_link] => admin/list_invoice.app
                )
            [6] => Array
                (
                    [id] => 3
                    [user_type] => Accountant
                    [latest_user_activity_date] => 2000-00-00 00:00:00
                    [full_link] => admin/create_invoice.app
                )
        )
    [admin] => Array
        (
            [4] => Array
                (
                    [id] => 1
                    [user_type] => Accountant
                    [latest_user_activity_date] => 2018-04-19 13:18:59.112704
                    [full_link] => admin/billing_contacts.app
                )
            [5] => Array
                (
                    [id] => 2
                    [user_type] => Accountant
                    [latest_user_activity_date] => 2018-04-15 13:18:59.112704
                    [full_link] => admin/client_upload.app
                )
            [2] => Array
                (
                    [id] => 3
                    [user_type] => Accountant
                    [latest_user_activity_date] => 2000-00-00 00:00:00
                    [full_link] => admin/billing_contacts.app
                )
        )
)

As you can see the 'invoice' index is now on top because it has the latest value on 'latest_user_activity_date' field.


Solution

  • This custom sort function will do what you need:

    function customSort(array $array)
    {
        // Iterate through and sort second level array by most recent date
        foreach ($array as $key => &$value) {
            usort($value, function ($a, $b) {
                return strtotime($a['latest_user_activity_date']) < strtotime($b['latest_user_activity_date']) ? 1 : -1;
            });
        }
    
        // Sort first level array by date descending of first (most recent) entry
        uasort($array, function ($a, $b) {
            return strtotime($a[0]['latest_user_activity_date']) < strtotime($b[0]['latest_user_activity_date']) ? 1 : -1;
        });
    
        return $array;
    }
    

    And here's a working example: https://3v4l.org/oZvJv