2

I am basing my code on the following link: PHP Multidimensional Array Searching (Find key by specific value) I attempted to add code similar to Get most recent date from an array of dates ; however I kept receiving illegal offset errors.

I can successfully select the proper value based on the first code. How can I then narrow down my return based on the most recent date in the array?

I am using php 5.4.45 and my array is always sorted by date with the most recent being last. I cannot simply select the last array index as it is not always a "Paid" order status.

My Array:

array(4) { 
[0]=> array(3) { 
    ["status"]=> string(6) "Active" 
    ["check_number"]=> string(0) "" 
    ["date_added"]=> string(19) "17/11/2015 10:34:53" } 
[1]=> array(3) { 
    ["status"]=> string(4) "Paid" 
    ["check_number"]=> string(5) "12345" 
    ["date_added"]=> string(19) "14/12/2015 07:40:59" } 
[2]=> array(3) { 
    ["status"]=> string(8) "Invoiced" 
    ["check_number"]=> string(0) ""  
    ["date_added"]=> string(19) "14/12/2015 09:44:31" } 
[3]=> array(3) { 
    ["status"]=> string(4) "Paid" 
    ["check_number"]=> string(4) "0258" 
    ["date_added"]=> string(19) "14/12/2015 09:53:29" } 
} 

My code:

function getValue($fromSource, $field, $value, $get){
    if ($fromSource[$field] === $value) {
        return $fromSource[$get];
    };
    return false;
}
foreach ($order['order_history'] as $order_history) {
    var_dump(getValue($order_history, "status", "Paid", "check_number"));
}

Desired result: "0258" (where status = "Paid" and date = most recent)

Currently Receiving: "12345" "0258" (where status = "Paid")

Community
  • 1
  • 1
Becca
  • 209
  • 1
  • 3
  • 11

3 Answers3

1

Using array_walk we collect all the dates.

We transform the dates into timestamps, using createFromFormat and getTimestamp, so we can easily order them, not forgetting to pass a timezone.

We get the key of the highest timestamp, and use it to access the list of items.

$items being the initial array.

$dates = array();

$format = 'd/m/Y H:i:s';
$timezone = new DateTimeZone('UTC'); 

array_walk($items,function($item,$index) use(&$dates,$format,$timezone){
    $date = DateTime::createFromFormat($format, $item["date_added"],$timezone);
    $dates[$index] = $date->getTimestamp();
});

// get the key of the most recent date
$key = array_keys($dates, max($dates))[0];

// using the key get the item from the list
print_r($items[$key]) . PHP_EOL;

Will output

Array
(
    [status] => Paid
    [check_number] => 0258
    [date_added] => 14/12/2015 09:53:29
)

From here you can easily access only one element of the result

print $items[$key]["check_number"];

Will output

0258
Alex Andrei
  • 7,315
  • 3
  • 28
  • 42
0

If the array is always sorted, you can use this code to get the newest entry matching the corresponding status:

    function getLatest($arr, $field, $value, $getField){

        for($i=count($arr)-1;$i >= 0; $i--){
                $currSubArr = $arr[$i];
                if($currSubArr[$field] === $value){
                    return $currSubArr[$getField];

                }   

        }
    }
    $orders[] = array('status' => 'active', 'checknumber'=> '121234','date_added' => '17/11/2015 10:34:53');
    $orders[] = array('status' => 'paid', 'checknumber' => '1212334','date_added' => '17/11/2015 10:38:53');
    $orders[] = array('status' => 'paid', 'checknumber '=> '5234','date_added' => '17/11/2015 10:42:53');



  //test --> returns 5234 
    echo getLatest($orders,'status','paid','checknumber');
eol
  • 23,236
  • 5
  • 46
  • 64
0

I think another possibility is to loop your array with a foreach construct and check for every array in the iteration if "status" is "Paid". Then every iteration you can compare the date from the current $item with the date in the $result array by using a DateTime object.

For example:

$items = array(
    array(
        "status" => "Active",
        "check_number" => "",
        "date_added" => "17/11/2015 10:34:53"
    ),
    array(
        "status" => "Paid",
        "check_number" => "12345",
        "date_added" => "14/12/2015 07:40:59"
    ),
    array(
        "status" => "Invoiced",
        "check_number" => "",
        "date_added" => "14/12/2015 09:44:31"
    ),
    array(
        "status" => "Paid",
        "check_number" => "0258",
        "date_added" => "14/12/2015 09:53:29"
    )
);

$result = array();

foreach ($items as $item) {
    if ($item["status"] === "Paid") {

        // If there is no result yet with status "Paid", then add it.
        if (count($result) === 0) {
            $result = $item;
            continue;
        }

        $itemDateTime = DateTime::createFromFormat('d/m/Y H:i:s', $item["date_added"]);
        $resultDateTime = DateTime::createFromFormat('d/m/Y H:i:s', $result["date_added"]);

        if ($itemDateTime > $resultDateTime) {
            $result = $item;
        }
    }
}

var_dump($result);

Will result in:

array (size=3)
  'status' => string 'Paid' (length=4)
  'check_number' => string '0258' (length=4)
  'date_added' => string '14/12/2015 09:53:29' (length=19)

Then you can access your value from the $result array like this:

echo $result["check_number"];

Will result in:

0258

Demo

The fourth bird
  • 154,723
  • 16
  • 55
  • 70