Array containing keys and associative array, how to make a relation - php

I have an array which contains the path to a specific value from an other array, to make it a bit more clear, here is an exemple.
My array containing the keys which I'll call $params
Array
(
[0] => paths
[1] => assets
[2] => js
)
And here is my associative array which I'll call $config
Array
(
[paths] => Array
(
[assets] => Array
(
[js] => /assets/js
[css] => /assets/css
)
)
[library] => Array
(
[js] => jQuery
)
)
So how could I use my array 1 to access the value in my array 2?
I tried $config[$params[0]][$params[1]][$params[2]], but it's not efficient at all.

You can try
$path = array(
0 => 'paths',
1 => 'assets',
2 => 'js',
);
$data = array(
'paths' => array(
'assets' => array(
'js' => '/assets/js',
'css' => '/assets/css',
),
),
'library' => array(
'js' => 'jQuery',
),
);
$temp = $data;
foreach($path as $key) {
$temp = $temp[$key];
}
var_dump($temp);
Output
string '/assets/js' (length=10)

A loop should solve your problem:
$c = $config;
foreach($params as $path) {
if(!array_key_exists($path, $c)) {
$c = null;
break;
}
$c = $c[$path];
}
This will iterate over every entry in $params and then access the subkey of the $config array. After finding it, $c will contain the current subarray. In the end, $c will contain the value you were looking for (NULL if the path was invalid/not found).
The same can be done in a functional way using the array_reduce function:
$path = array_reduce(function($current, $path) {
if($current == NULL || !array_key_exists($path, $current))
return NULL;
return $current[$path];
}, $params, $config);

Hi Jonathan here you have missed one brace in the end
try this "$config[$params[0]][$params[1]][$params[2]]".
It will work
I am posting a code which worked fine for me
<?php
$params = array(0 => 'paths',1 => 'assets',2 => 'js');
echo '<pre>';print_r($params);
$config = array
(
'paths' => array
(
'assets' => array
(
'js' => '/assets/js',
'css' => '/assets/css'
)
),
'library' => array
(
'js' => 'jQuery'
)
);
echo '<pre>';print_r($config);
echo $config[$params[0]][$params[1]][$params[2]];
?>

Related

Unexpected behavior in recursive function

The task is to remove arrays recursively that have error => 4 (i.e key with that value) with their keys, and then turn remained arrays into objects.
The structure of incoming array might be different. Two examples of it are this ones:
// Example input #1
$ex_input_1 = array(
'files' => array(
0 => array(
'name' => 'file.jpg',
'size' => '244235',
'tmp_name' => '/usr/tmp/24ffds.tmp',
'error' => 0
),
1 => array(
'name' => '',
'size' => '',
'tmp_name' => '',
'error' => 4
)
),
'cover' => array(
'name' => '',
'size' => '',
'tmp_name' => '',
'error' => 4
),
'document' => array(
'name' => 'file.doc',
'size' => '244235',
'tmp_name' => '/usr/tmp/24ffds.tmp',
'error' => 0
)
);
// Example input #2
$ex_input_2 = array(
0 => array(
'name' => 'file.jpg',
'size' => '244235',
'tmp_name' => '/usr/tmp/24ffds.tmp',
'error' => 0
),
1 => array(
'name' => '',
'size' => '',
'tmp_name' => '',
'error' => 4
)
);
i.e an array that have name, size, tmp_name, error keys might be at any level down.
What I tried:
Tried to write a simple handler with two methods, where the first one is recursive handler and the second one is hydrator method. Here's it with relevant parts:
<?php
class FileInputParser
{
/**
* Recursively hydrate array entires skipping empty files
*
* #param array $files
* #return array
*/
public function hydrateAll(array $files)
{
foreach ($files as $name => $file) {
if (!is_array($file)) {
continue;
}
foreach ($file as $key => $value) {
if (is_array($value)) {
// Recursise call
$files[$name] = $this->hydrateAll($files[$name]);
} else {
$target = $this->hydrateSingle($file);
// Here I'm EXPLICTLY asking not to push an array, which has error = 4
// But it pushes anyway!!
if ($target !== false) {
unset($files[$name]);
}
}
}
}
return $files;
}
/**
* Hydrates a single file item
*
* #param array $file
* #return mixed
*/
private function hydrateSingle(array $file)
{
$entity = new stdclass;
$entity->name = $file['name'];
$entity->tmp_name = $file['tmp_name'];
$entity->error = $file['error'];
$entity->size = $file['size'];
if ($entity->error != 4) {
return $entity;
} else {
// Returning false to indicate, that this one should not be pushed in output
return false;
}
}
}
The problem
While at first glance it works, the problem is that, when I'm asking explicitly not to add an array that has error = 4 to output, but it continues to add!
You can run aforementioned code with input examples:
<?php
$parser = new FileInputParser();
$output = $parser->hydrateAll($ex_input_1);
echo '<pre>', print_r($output, true);
to see that it also returns unwanted arrays (i.e the ones that have error = 4).
The question
Why it continues to add arrays to output that have error = 4 ?
if you have a better idea on handling this, I'd love to hear it.
Here's a recursive function that will do the filtering you want. When it reaches the bottom of the tree, it checks for error == 4 and if it is, returns an empty array, otherwise it returns the current array. At the next level down any empty values returned are removed by array_filter:
function array_filter_recursive($array) {
if (isset($array['error'])) {
// bottom of tree
return $array['error'] == 4 ? array() : $array;
}
foreach ($array as $key => $value) {
$array[$key] = array_filter_recursive($value);
}
// remove any empty values
return array_filter($array);
}
Output from filtering your two input arrays:
Array (
[files] => Array (
[0] => Array (
[name] => file.jpg
[size] => 244235
[tmp_name] => /usr/tmp/24ffds.tmp
[error] => 0
)
)
[document] => Array (
[name] => file.doc
[size] => 244235
[tmp_name] => /usr/tmp/24ffds.tmp
[error] => 0
)
)
Array (
[0] => Array (
[name] => file.jpg
[size] => 244235
[tmp_name] => /usr/tmp/24ffds.tmp
[error] => 0
)
)
Demo on 3v4l.org

Delete/unset an array element matching a key/value of another array element [PHP]

I have the following multidimensional array:
$messages = array(
'message1'=>array(
'type'=>'voice',
'call-id'=>'11'
'id'='message1'
),
'message2'=>array(
'type'=>'voice',
'call-id'=>'44'
'id'='message2'
),
'message3'=>array(
'type'=>'text',
'call-id'=>'44'
'id'='message3'
),
'message4'=>array(
'type'=>'text',
'call-id'=>'55'
'id'='message4'
),
'message5'=>array(
'type'=>'voice',
'call-id'=>'55'
'id'='message5'
),
);
I need to delete/unset for example $messages['message2'], because there is another array element($messages['message3']) with keys and values('type'=>'text', 'call-id'=>'44').
Basically, if we have two elements with the same call-id, then delete the element with type = voice.
So, the result of the array above should be:
$messages = array(
'message1'=>array(
'type'=>'voice',
'call-id'=>'11'
'id'='message1'
),
'message3'=>array(
'type'=>'text',
'call-id'=>'44'
'id'='message3'
),
'message4'=>array(
'type'=>'text',
'call-id'=>'55'
'id'='message4'
),
);
Try this:
<?php
$messages = array(
'message1'=>array(
'type'=>'voice',
'call-id'=>'11',
'id'=>'message1'
),
'message2'=>array(
'type'=>'voice',
'call-id'=>'44',
'id'=>'message2'
),
'message3'=>array(
'type'=>'text',
'call-id'=>'44',
'id'=>'message3'
),
'message4'=>array(
'type'=>'text',
'call-id'=>'55',
'id'=>'message4'
),
'message5'=>array(
'type'=>'voice',
'call-id'=>'55',
'id'=>'message5'
),
);
$unique = [];
foreach ($messages as $value) {
if ($value['type'] == 'text') {
$unique[$value['call-id']] = $value;
// so text comes first and override any previous value with the same call-id
} else if (!array_key_exists($value['call-id'], $unique)) {
$unique[$value['call-id']] = $value;
// will be added only if no same call-id and will be overridden if same call-id with type text after
}
}
foreach ($unique as $value) {
$array[$value['id']] = $value;
}
echo '<pre>';
print_r($array);
OUTPUT:
Array
(
[message1] => Array
(
[type] => voice
[call-id] => 11
[id] => message1
)
[message3] => Array
(
[type] => text
[call-id] => 44
[id] => message3
)
[message4] => Array
(
[type] => text
[call-id] => 55
[id] => message4
)
)
http://www.phpwin.org/s/LJxrQw

How do I reform this array into a differently structured array

I have an array that looks like this:
[0] => Array
(
[name] => typeOfMusic
[value] => this_music_choice
)
[1] => Array
(
[name] => myMusicChoice
[value] => 9
)
[2] => Array
(
[name] => myMusicChoice
[value] => 8
)
I would like to reform this into something with roughly the following structure:
Array(
"typeOfMusic" => "this_music_choice",
"myMusicChoice" => array(9, 8)
)
I have written the following but it doesn't work:
foreach($originalArray as $key => $value) {
if( !empty($return[$value["name"]]) ){
$return[$value["name"]][] = $value["value"];
} else {
$return[$value["name"]] = $value["value"];
}
}
return $return;
I've tried lots of different combinations to try and get this working. My original array could contain several sets of keys that need converting to arrays (i.e. it's not always going to be just "myMusicChoice" that needs converting to an array) ?
I'm getting nowhere with this and would appreciate a little help. Many thanks.
You just need to loop over the data and create a new array with the name/value. If you see a repeat name, then change the value into an array.
Something like this:
$return = array();
foreach($originalArray as $data){
if(!isset($return[$data['name']])){
// This is the first time we've seen this name,
// it's not in $return, so let's add it
$return[$data['name']] = $data['value'];
}
elseif(!is_array($return[$data['name']])){
// We've seen this key before, but it's not already an array
// let's convert it to an array
$return[$data['name']] = array($return[$data['name']], $data['value']);
}
else{
// We've seen this key before, so let's just add to the array
$return[$data['name']][] = $data['value'];
}
}
DEMO: https://eval.in/173852
Here's a clean solution, which uses array_reduce
$a = [
[
'name' => 'typeOfMusic',
'value' => 'this_music_choice'
],
[
'name' => 'myMusicChoice',
'value' => 9
],
[
'name' => 'myMusicChoice',
'value' => 8
]
];
$r = array_reduce($a, function(&$array, $item){
// Has this key been initialized yet?
if (empty($array[$item['name']])) {
$array[$item['name']] = [];
}
$array[$item['name']][] = $item['value'];
return $array;
}, []);
$arr = array(
0 => array(
'name' => 'typeOfMusic',
'value' => 'this_music_choice'
),
1 => array(
'name' => 'myMusicChoice',
'value' => 9
),
2 => array(
'name' => 'myMusicChoice',
'value' => 8
)
);
$newArr = array();
$name = 'name';
$value = 'value';
$x = 0;
foreach($arr as $row) {
if ($x == 0) {
$newArr[$row[$$name]] = $row[$$value];
} else {
if (! is_array($newArr[$row[$$name]])) {
$newArr[$row[$$name]] = array();
}
array_push($newArr[$row[$$name]], $row[$$value]);
}
$x++;
}

To print the value of array.under array

I have to print the all the value of the array written value.
[subscriber] => Array
(
[name] => Subscriber
[capabilities] => Array
(
[read] => 1
[level_0] => 1
)
[default] => Array
(
[deft] => Array (
[one] => 2
[two] => 3
)
[deft_one] => Array (
[one] => t
[two] => h
)
)
)
I have to print each value under the array. So i used a recursion function. But i cant the result. Please help me in recursion function.
Sorry, I am trying till now. Actually i have to print the wp-option table value. There are many serialise array. I want to print all the value individually. I mean when i used the code written bellow i got an array.
function option_value_change () {
global $wpdb;
$myrows = $wpdb->get_results( "SELECT *
FROM `wp_options`");
$temp_url = get_option('siteurl');
$site_url = get_site_url();
foreach ($myrows as $rows){
$option = get_option($rows->option_name);
//print_r($option);
get_option_value($option);
}
}
i can get the table. But in an array. Which array have arrays. So i used an function "get_option_value($option)". as written bellow
function get_option_value($option) {
if(!is_object($option) && !is_array($option)){
echo $option;
}
else{
foreach($option as $option_value){
if(!is_array($option_value)){
echo $option_value;
}
else {
get_option_value($option_value);
}
}
}
}
bUt i cant get all the value. its give an error as
Object of class stdClass could not be converted to string.
So how can i print all the values of the array.
You can use RecursiveArrayIterator example :
$data = array(
'subscriber' => array(
'name' => 'Subscriber',
'capabilities' => array(
'read' => 1,
'level_0' => 1,
),
'default' => array(
'deft' => array(
'one' => 2,
'two' => 3,
),
'deft_one' => array(
'one' => 't',
'two' => 'h',
),
),
),
);
echo "<pre>";
$it = new RecursiveIteratorIterator(new RecursiveArrayIterator($data));
foreach($it as $var)
{
echo $var , PHP_EOL ;
}
Output
Subscriber
1
1
2
3
t
h
I didn't test it but you can get the idea;
function printArr($obj){
if(!is_array($obj)){
echo $obj;
return;
}
else if(is_array($obj)){
foreach ($obj as $key => $value) {
printArr($obj[$key]);
}
}
}

Retrieve all parent keys of a given child key in Array

I've been breaking my head over this one but can't seem to find a solution. I need a function that retrieves all parent keys of a given child key. So for example if I have an array like this:
array(
'apples' => array(
'bananas' => array(
'strawberries' => array(
'fruit' => array()
)
)
)
)
I would call the function like 'key_get_parents($key, $array)', and it would return an array with all the parent keys. In this example that would be array('apples', 'bananas', 'strawberries').
$array = array(
'apples' => array(
'bananas' => array(
'strawberries' => array(
'fruit' => array()
)
)
)
);
function key_get_parents($subject, $array)
{
foreach ($array as $key => $value)
{
if (is_array($value))
{
if (in_array($subject, array_keys($value)))
return array($key);
else
{
$chain = key_get_parents($subject, $value);
if (!is_null($chain))
return array_merge(array($key), $chain);
}
}
}
return null;
}
// Prints "Array ( [0] => apples [1] => bananas )"
print_r(key_get_parents('strawberries', $array));

Categories