Reputation: 1233
I've following data in my Database :
| meta_key | meta_value |
|-----------------------------------|------------|
| foo | bar |
| hello | world |
| testimonials_0_category | category0 |
| testimonials_0_comments_0_message | message0 |
| testimonials_0_comments_1_message | message1 |
Some of the meta_key will be string and some of the meta_key will be nested array base on the _{N}_
pattern.
I've successfully extract & render the data as I wanted with eval(); method, but i don't think eval is a good solution for this.
I'm just wondering do we have alternative solution on this (eg : using recursive or other kind of array loop method?)
You may refer below for my sample codes:
<?php
$database = array();
$database[] = array('meta_key' => 'foo','meta_value'=>'bar');
$database[] = array('meta_key' => 'hello','meta_value'=>'world');
$database[] = array('meta_key' => 'testimonials_0_category','meta_value'=>'category0');
$database[] = array('meta_key' => 'testimonials_0_comments_0_message','meta_value'=>'message0');
$database[] = array('meta_key' => 'testimonials_0_comments_1_message','meta_value'=>'message1');
$output = array();
// echo'<pre>';print_r($database);die;
foreach($database as $d)
{
if (preg_match('(_\d+_)',$d['meta_key']))
{
//nested array
preg_match_all('(_\d+_)',$d['meta_key']."_9999_x",$matches);
$splits = preg_split('(_[0-9]_)', $d['meta_key']);
$str = '';
foreach($matches[0] as $j => $match)
{
$i = filter_var($match,FILTER_SANITIZE_NUMBER_INT);
$str.= "['{$splits[$j]}'][{$i}]";
}
$str = Str_replaceLast('[9999]','',$str);
eval('$output'.$str." = '{$d['meta_value']}';");
}else{
//string
$output[$d['meta_key']] = $d['meta_value'];
}
}
echo'<pre>';print_r($output);
//Helper
function Str_replaceLast($search, $replace, $subject)
{
$position = strrpos($subject, $search);
if ($position !== false) {
return substr_replace($subject, $replace, $position, strlen($search));
}
return $subject;
}
?>
The result/output I want would be like below format:
Array
(
[foo] => bar
[hello] => world
[testimonials] => Array
(
[0] => Array
(
[category] => category0
[comments] => Array
(
[0] => Array
(
[message] => message0
)
[1] => Array
(
[message] => message1
)
)
)
)
)
Upvotes: 0
Views: 67
Reputation: 147216
This recursive function will give you the results you want. It splits the meta_key
value into three parts around and including the number and uses that to create a new entry in the output array. If there is more than 1 part of the key remaining, the function recurses to the next level on the part of the key after the digit, otherwise it assigns the meta_value
to that part of the key:
function split_word($word, $value, $output) {
$parts = preg_split('/_(\d)+_/', $word, 2, PREG_SPLIT_DELIM_CAPTURE);
if (count($parts) > 1) {
if (isset($output[$parts[0]][$parts[1]])) {
$output[$parts[0]][$parts[1]] = array_merge($output[$parts[0]][$parts[1]], split_word($parts[2], $value, $output[$parts[0]][$parts[1]]));
}
else {
$output[$parts[0]][$parts[1]] = split_word($parts[2], $value, array());
}
}
else {
$output = array_merge($output, array($word => $value));
}
return $output;
}
$output = array();
foreach ($database as $d) {
$output = array_merge($output, split_word($d['meta_key'], $d['meta_value'], $output));
}
print_r($output);
Output:
Array
(
[foo] => bar
[hello] => world
[testimonials] => Array
(
[0] => Array
(
[category] => category0
[comments] => Array
(
[0] => Array
(
[message] => message0
)
[1] => Array
(
[message] => message1
)
)
)
)
)
Upvotes: 1