Reputation: 1625
I'm trying to get one of the 'main' array ('111', '222') where the 'expire' attribute is past from current timestamp.
my array is structured like this:
$stored = array(
'111' => array(
0 => array(
'type' => 'first',
'expire' => date('Y-m-d H:i:s', strtotime('2019-01-01 08:00:00')),
),
1 => array(
'type' => 'second',
'expire' => date('Y-m-d H:i:s', strtotime('2019-01-01 09:00:00')),
),
),
'222' => array(
0 => array(
'type' => 'first',
'expire' => date('Y-m-d H:i:s', strtotime('2019-01-02 12:00:00')),
),
1 => array(
'type' => 'second',
'expire' => date('Y-m-d H:i:s', strtotime('2019-01-02 13:00:00')),
),
2 => array(
'type' => 'third',
'expire' => date('Y-m-d H:i:s', strtotime('2019-01-02 14:00:00')),
),
),
);
I did a bit of research and found array_column
which I feel to be a part of the solution but I don't know how to apply it to my case since I tried
$list = array_column($stored, 'expire');
print_r($list);
and it gives an empty array, so it means array_column
doesn't work on multidimensional array..
Upvotes: 0
Views: 130
Reputation: 970
Using your code
// an array to hold all the expired dates
$expired = [];
$stored = array(
'111' => array(
0 => array(
'type' => 'first',
'expire' => date('Y-m-d H:i:s', strtotime('2019-08-01 08:00:00')),
),
1 => array(
'type' => 'second',
'expire' => date('Y-m-d H:i:s', strtotime('2019-01-01 09:00:00')),
),
),
'222' => array(
0 => array(
'type' => 'first',
'expire' => date('Y-m-d H:i:s', strtotime('2019-01-02 12:00:00')),
),
1 => array(
'type' => 'second',
'expire' => date('Y-m-d H:i:s', strtotime('2019-01-02 13:00:00')),
),
2 => array(
'type' => 'third',
'expire' => date('Y-m-d H:i:s', strtotime('2019-01-02 14:00:00')),
),
),
);
// Loop through the first/parent array
foreach($stored as $key => $val){
// Get the expire index only and store into variable for use in the inner loop
$expire_dates = array_column($val, 'expire');
// Loop through the inner arrays
foreach($val as $value){
// Convert the expire date from 'Y-m-d H:i:s' to unix timestamp, it is easier and better for date comparison
$expire = strtotime($value['expire']);
if($expire < time() ){
$expired[$key][] = $value['expire'];
}
}
}
// Now print all the expired array data
echo '<pre>';
print_r($expired);
Expected Output:
Array
(
[111] => Array
(
[0] => 2019-01-01 09:00:00
)
[222] => Array
(
[0] => 2019-01-02 12:00:00
[1] => 2019-01-02 13:00:00
[2] => 2019-01-02 14:00:00
)
)
Upvotes: 0
Reputation: 57141
A couple of nested foreach
loops are the most efficient (IMHO) as the inner loop checks for an expired entry. As soon as one is found it flags the whole key and then moves onto the next one. This saves having to process all of the entries and then check if any are left...
$expired = [];
foreach ( $stored as $key => $main ) {
foreach ( $main as $sub ) {
if ( strtotime($sub['expire']) < time() ) {
$expired[] = $key;
break;
}
}
}
print_r($expired);
If you just want the first expired one, then change
break;
to
break 2;
and it will stop both loops as soon as it finds an expired item.
Upvotes: 1
Reputation: 3128
You could just loop over each of the collections of items, and then use array_filter
to determine if any of the items are expired. For example:
$expiredKeys = [];
foreach ($stored as $key => $items) {
$hasExpired = count(array_filter($items, function ($item) {
return strtotime($item['expire']) < time();
})) > 0;
if ($hasExpired) {
$expiredKeys[] = $key;
}
}
var_dump($expiredKeys);
Outputs:
array(2) {
[0] =>
int(111)
[1] =>
int(222)
}
Upvotes: 0