I'm working on project and I'm trying to refactor an json object By array of $keys for example:
- as input:
{
"message": "User Detail",
"code": 200,
"error": false,
"results": {
"user": {
"id": 2,
"name": "ali",
"country": {
"id": 50,
"name": "EGY"
}
},
"access_token": "=PQLkHJYIXB2uKbCq4sXIjD2GpBU2o"
}
}
- as input: array of $keys
$kyes = [
'code',
'user'=>[
'id',
'country'=>['name']
]
]
expect to return:
{
"code": 200,
"user": {
"id": 2,
"country": {
"name": "egy",
}
}
}
code I have tried:
public function filter_multidimensional(array $array, array $keys){
$val = [];
foreach ($array as $key => $value) {
if (in_array($key,$keys)){
$val[$key] = $value;
}elseif (is_array($value)) {
$val[$key] = $this->filter_multidimensional($keys,$value);
}
}
return $val;
}
//-------
$this->filter_multidimensional($json,['code','user'=>['id','country'=>['name']]])
update 1
the json input is not const, so my code must to adapt. and that's I'm trying to do
CodePudding user response:
You could use a combination of data_get
and data_set
to get what you want.
Change the input a bit so it's more consistent. Dot notation would be easiest.
$array = [
"message" => "User Detail",
"code" => 200,
"error" => false,
"results" => [
"user" => [
"id" => 2,
"name" => "ali",
"country" => [
"id" => 50,
"name" => "EGY",
],
],
"access_token" => "=PQLkHJYIXB2uKbCq4sXIjD2GpBU2o",
],
];
$keys = [
'code' => 'code',
'user.id' => 'results.user.id',
'user.country.name' => 'results.user.country.name',
];
$results = [];
foreach ($keys as $set_position => $get_position) {
data_set($results, $set_position, data_get($array, $get_position));
}
CodePudding user response:
I believe this method works. I flipped your logic, and instead of searching the $array
to see if it's keys match any of those in $keys
, I instead recursively searched $keys
to see if $array
had any matching values.
function filter_multidimensional(array $array, array $keys) {
if (empty($keys) || empty($array)) {
return [];
}
$val = [];
// In the structure of $keys, both key and value are technically "keys".
// In the example `['code','user'=>['id']]`, 'code' and 'id' are both array *values*,
// while 'user' is a key.
//
// So, $objectKey is a search key which contains sub-keys, while $key is just a regular string.
foreach ($keys as $objectKey => $key) {
// If $key is an array, then recursively search, and save the results to the $objectKey string.
if (is_array($key)) {
$val[$objectKey] = filter_multidimensional($array, $key);
}
// If the desired key exists, then save the value.
else if (array_key_exists($key, $array)) {
$val[$key] = $array[$key];
}
// Otherwise, $key is a string, but it does not exist at this level of $array,
// so search the next-level up in $array, and merge the results into this level of $val.
else {
$val = array_merge($val, filter_multidimensional(nextLevel($array), [$key]));
}
}
return $val;
}
/**
* Create an array that contains only the array values from $array.
*
* Eg: If given ['a' => '1', 'b' => ['foo' => '2'], 'c' => ['hello' => 'world']],
* then return ['foo' => '2', 'hello' => 'world']
*
* @param array $array
* @return array
*/
function nextLevel(array $array) {
// Merge all of the array values together into one array
return array_reduce(
// Strip the keys
array_values(
// Filter to return only keys where the value is an array
array_filter(
$array,
function ($value) {
return is_array($value);
}
)
),
'array_merge',
[]
);
}
//-------
$result = filter_multidimensional($obj,['code','user'=>['id','country'=>['name']]]);