php - Can't figure out the usort logic based on 2 variables -
i have array of objects (goals) want sort based on 2 of properties, status
, duedate
.
here rules:
statuses:
- design
- approved
- in progress
- completed
- archived
if goal has status of 4 (completed) or 5 (archived) duedate
doesn't matter.
if goal neither 4 nor 5 , duedate
less "overdue" , should @ top
if goal not "overdue" order of statuses determines it's position (lowest highest)
if $a
, $b
both "overdue" 1 earliest duedate
more important
the order should be:
- overdue
- design
- approved
- in progress
- completed
- archived
here last thing tried:
function cmp($a, $b) { $now = new datetime("now"); $aduedate = new datetime($a->getduedate()); $bduedate = new datetime($b->getduedate()); if($a->getstatus() != 4 && $a->getstatus() != 5 && $b->getstatus() != 4 && $b->getstatus() != 5){ if($aduedate < $now || $bduedate < $now){ if($aduedate == $bduedate){ return 0; } return ($aduedate < $bduedate) ? -1 : 1; } } elseif(($a->getstatus() == 4 || $a->getstatus() == 5) && ($b->getstatus() != 4 && $b->getstatus() != 5)) { return -1; } elseif(($a->getstatus() != 4 && $a->getstatus() != 5) && ($b->getstatus() == 4 || $b->getstatus() == 5)){ return 1; } if ($a->getstatus() == $b->getstatus()) { return 0; } return ($a->getstatus() < $b->getstatus()) ? -1 : 1; }
which orders array so:
- completed
- archived
- overdue
- design
- approved
- in progress
the following should meet requirements:
function cmp($a, $b) { $now = new datetime("now"); $aduedate = new datetime($a->getduedate()); $bduedate = new datetime($b->getduedate()); $astatus = $a->getstatus(); $bstatus = $b->getstatus(); $incompletestatuses = array(1, 2, 3); // use date if same status (might not needed) if ($astatus == $bstatus) { return ($aduedate < $bduedate ? -1 : 1); } // if overdue: if (in_array($astatus, $incompletestatuses) && $aduedate < $now) { // if b overdue too, consider dates if (in_array($bstatus, $incompletestatuses) && $bduedate < $now) { return ($aduedate < $bduedate ? -1 : 1); } return -1; // first } // if b overdue: elseif (in_array($bstatus, $incompletestatuses) && $bduedate < $now) { return 1; // b first (we know not overdue above) } // both , b not overdue; order status return $astatus - $bstatus; }