I have a problem writing a code in which I can arrive at the values, but using text or an array
Suppose this Array:
$array = [
'name' => 'any Name',
'settings' => [
'app' => 'Spy',
'location' => 'Earth',
'locale' => 'en'
]
];
and i want to get app value
default code:
echo $array['settings']['app'];
But this method is not working because I cannot write the parentheses [] [] in my case
I want a method similar to this:
$handle = 'app, name';
echo $array[$handle] ;
or
$handle = ['settings']['app'];
echo $array[$handle];
I know that the code is wrong, but an example
I hope that the idea has arrived and that there is a solution.
Could it be something like that?
<?php
$array = [
'name' => 'any Name',
'settings' => [
'app' => 'Spy',
'location' => 'Earth',
'locale' => 'en'
]
];
$str = 'settings|app'; // this is string you have
foreach (explode('|', $str) as $key) {
if (!isset($output)) {
$output = $array[$key];
} else {
$output = $output[$key];
}
}
echo $output; // spy
Related
My array looks some what like this (is has multiple sub arrays)
[
'reportId' => '20210623-da1ece3f'
'creationDate' => '2021-06-23 19:50:15'
'dueDate' => '2021-06-24 19:50:15'
'data' => [
'vehicleDetails' => [
'chassisNumber' => 'xxxxx-xxxxxx'
'make' => 'Honda'
'model' => 'City'
'manufactureDate' => '2000'
'body' => 'xxx-xxxxx'
'engine' => 'xxx-xxx'
'drive' => 'FF'
'transmission' => 'MT'
]
]
i'm trying to rename all keys from chassisNumber to chassis_number. This is what i've done so far
function changeArrayKeys($array)
{
if(!is_array($array)) return $array;
$tempArray = array();
foreach ($array as $key=>$value){
if(is_array($value)){
$value = changeArrayKeys($value);
}else{
$key = strtolower(trim(preg_replace('/([A-Z])/', '_$1', $key)));
}
$tempArray[$key]=$value;
}
return $tempArray;
}
print_r(changeArrayKeys($data)); die;
This code kind of works. it just doesn't replace the sub keys. like here
'data' => [
'vehicleDetails' => [ ]
]
but inside vehicleDetails[] it replace properly. Any idea what im missing here? or is there a better and more efficient way to do this instead of recursively ?
This looks pretty obvious to me:
if(is_array($value)){
$value = changeArrayKeys($value);
}else{
$key = strtolower(trim(preg_replace('/([A-Z])/', '_$1', $key)));
}
If the $value is an array, you do a recursive call, but you do not change the key of that nested array in any way. It could help to move the $key manipulation out of the else branch
I have a result set from a query that gives me an object that has dozens of fields, the below example is a subset:
[79] => stdClass Object
(
[name] => John Doe
[email] => john#doe.com
[ext] => 4004
[options] => stdClass Object
(
[type] => friend
[rating] => Excellent
[context] => default
)
[address] => 123 Anywhere St
)
Instead of plowing through each field, because I only want a handful of them, I am trying to use an array to get what i want:
$fields = array('name','email','options->type','options->rating','address');
so then i do:
foreach ($result as $k => $v){
foreach ($fields as $kk => $vv){
echo $kk. " - " . $v->$kk."<br>";
}
}
Which gives me field name and its value.
name - John Doe
email - john#doe.com
address - 123 Anywhere St.
However, anything in that sub object(options) is giving me a blank result.
You can use a recursive function providing that you don't mind changing the format of your $fields var to include arrays. In my opinion this makes it easier to read anyway, and easier to handle in code.
The benefit of using a recursive function is that it will handle any depth.
$o = (object) [
'name' => 'John Doe',
'email' => 'john#doe.com',
'ext' => 4004,
'options' => (object) [
'type' => 'friend',
'rating' => 'Excellent',
'context' => 'default',
'any' => (object) [
'depth' => (object) [
'will' => 'work'
]
]
],
'address' => '123 Anywhere St'
];
$fields = [
'name',
'email',
'options' => [
'type',
'rating',
'any' => [
'depth' => [
'will'
]
]
],
'address'
];
function getObjectProps($o, $fields, $parent = '') {
if (strlen($parent)) {
$parent .= '->';
}
foreach ($fields as $k => $v) {
if (is_array($v)) {
getObjectProps($o->{$k}, $v, $parent . $k);
} else {
echo $parent . $v . ' - ' . $o->{$v} . '<br/>';
}
}
}
getObjectProps($o, $fields);
Output:
name - John Doe
email - john#doe.com
options->type - friend
options->rating - Excellent
options->any->depth->will - work
address - 123 Anywhere St
Use a multidimensionnal array for $fields and change your foreach loop a little bit:
$fields = [
'name',
'email',
'options' => [
'type',
'rating'
],
'address'
];
foreach ($result as $obj) {
foreach ($fields as $k => $v) {
if (is_array($v)) {
foreach ($v as $vv) {
echo $vv . ' - ' . $obj->$k->$vv . '<br>';
}
} else {
echo $v . ' - ' . $obj->$v . '<br>';
}
}
}
Here's what I came up with in the meantime
$someObject = new stdClass();
$someObject->name = 'Dale';
$someObject->options = new stdClass();
$someObject->options->address = 'The Address';
$fields = ['name', 'options' => ['address']];
function toArray($object, $fields) {
$return = [];
foreach($fields as $fieldKey => $fieldValue) {
if(!is_array($fieldValue)) {
$return [] = $object->$fieldValue;
}
else
{
$return = array_merge($return, toArray($object->$fieldKey, $fieldValue));
}
}
return $return;
}
print_r(toArray($someObject, $fields));
Try this code:
$newResult = array_intersect_key((array)$result, array_flip($fields));
There is no easy way to access property like the way you are trying. But there's a symfony's property access component which you can use. But if you are focusing to use your own method then you might love the following code. I ran this code in PHP 7.2
$data = (object) [
'name' => 'John Doe',
'email' => 'john#doe.com',
'ext' => 4004,
'options' => (object) [
'type' => "friend",
'rating' => 'Excellent',
'context' => 'default'
],
'address' => '123 Anywhere St'
];
$fields = array('name','email','options->type','options->rating','address');
/*** way of initializing
$response = []; // get array value here
$response = ""; // get string value here
***/
$response = ""; //string value here... as output
/*** Don't you think that the below code now is clean and reusable? ***/
array_map(function($key) use($data, &$response) {
$value = array_reduce(explode('->', $key), function ($o, $p) {
return $o->$p;
}, $data);
is_array($response) ? ($response[$key] = $value) : ($response .= $key . ' - ' . $value . '<br>');
}, $fields);
echo $response;
In the above code if you initialize $response as an empty array then you'll get array as output. And if you initialize that as an empty string then you'll get string output. And I think instead of using for loop, use array_map and array_reduce, they work like magic and reduce your code too.
String as output:
Array as ouput:
I have 2 arrays, I want match this arrays and get results with keys.
Can I search in first array with second array keys or match diffrent way?
$boardLists = [
[
'_id' => 'a1a1a1',
'name' => 'Board Name #1',
'code' => 'B1'
],
[
'_id' => 'b2b2b2',
'name' => 'Board Name #2',
'code' => 'B2
]
];
and
$boards = [
'a1a1a1',
'b2b2b2',
'c3c3c3'
];
My result with array_intersect:
array(1) { [0]=> string(6) "a1a1a1" }
My expected result if match 'a1a1a1':
[
'_id' => 'a1a1a1',
'name' => 'Board Name #1',
'code' => 'B1'
],
That I could understand you want to search in the first array according to what you have in the second array, so here is one example:
$boardLists = [
[
'_id' => 'a1a1a1',
'name' => 'Board Name #1',
'code' => 'B1'
],
[
'_id' => 'b2b2b2',
'name' => 'Board Name #2',
'code' => 'B2'
]
];
$boards = [
'a1a1a1',
'b2b2b2',
'c3c3c3'
];
$boardListIds = array_column($boardLists, '_id');
$results = [];
foreach ($boards as $board) {
$find_key = array_search($board, $boardListIds);
if($find_key !== false)
$results[] = $find_key;
}
#printing the results
foreach ($results as $result) {
print_r($boardLists[$result]);
}
There many ways to do it, this is just one. I hope it helps. :)
It would be more efficient to have the array index of your first array the _id. However with the way the array is setup currently you could do:
foreach($boards as $key1=>board){
foreach($boardLists as $key2=>$boardList){
if($boardList['_id']==$key1){
echo $key1 . PUP_EOL;
print_r($boardList);
}
}
}
Try this
$finalArray = array();
foreach($boardLists as $key=>$val):
if(in_array($val['_id'],$boards))
{
$finalArray[] = $val2;
}
endforeach;
I have an array:
<?php
$array = [
'fruits' => [
'apple' => 'value',
'orange' => 'value'
],
'vegetables' => [
'onion' => 'value',
'carrot' => 'value'
];
I also have a string:
$string = 'fruits[orange]';
Is there any way to check if the - array key specified in the string - exists in the array?
For example:
<?php
if(array_key_exists($string, $array))
{
echo 'Orange exists';
}
Try this one. Here we are using foreach and isset function.
Note: This solution will also work for more deeper levels Ex: fruits[orange][x][y]
Try this code snippet here
<?php
ini_set('display_errors', 1);
$array = [
'fruits' => [
'apple' => 'value',
'orange' => 'value'
],
'vegetables' => [
'onion' => 'value',
'carrot' => 'value'
]
];
$string = 'fruits[orange]';
$keys=preg_split("/\[|\]/", $string, -1, PREG_SPLIT_NO_EMPTY);
echo nestedIsset($array,$keys);
function nestedIsset($array,$keys)
{
foreach($keys as $key)
{
if(array_key_exists($key,$array))://checking for a key
$array=$array[$key];
else:
return false;//returning false if any of the key is not set
endif;
}
return true;//returning true as all are set.
}
It would be a lot easier to check the other way around. As in check if the key is in the string. Since keys are unique, there's no way you have duplicates.
$array = [
'fruits' => [
'apple' => 'value',
'orange' => 'value'
],
'vegetables' => [
'onion' => 'value',
'carrot' => 'value'
]
];
$string = 'fruits[orange]';
$keys = array_keys($array['fruits']);
foreach($keys as $fruit) {
if(false !== stripos($string, $fruit)) {
return true;
}
}
While this solution is not necessarily ideal, the problem to begin with isn't exactly common.
You can walk recursively:
$array = [
'fruits' => [
'apple' => 'value',
'orange' => 'value'
],
'vegetables' => [
'onion' => 'value',
'carrot' => 'value'
]
];
$exists = false;
$search = "orange";
array_walk_recursive($array, function ($val, $key) use (&$exists,$search) {
if ($search === $key) { $exists = true; }
});
echo ($exists?"Exists":"Doesn't exist");
Prints:
Exists
Example: http://sandbox.onlinephpfunctions.com/code/a3ffe7df25037476979f4b988c2f36f35742c217
Instead of using regex or strpos like the other answers, you could also simply split your $string on [ and resolve the keys one by one until there's only one key left. Then use that last key in combination with array_key_exists() to check for your item.
This should work for any amount of dimensions (eg fruit[apple][value][1]).
Example:
<?php
$arr = [
'fruits' => [
'orange' => 'value'
]
];
// Resolve keys by splitting on '[' and removing ']' from the results
$keys = 'fruits[orange]';
$keys = explode("[", $keys);
$keys = array_map(function($s) {
return str_replace("]", "", $s);
}, $keys);
// Resolve item.
// Stop before the last key.
$item = $arr;
for($i = 0; $i < count($keys) - 1; $i++) {
$item = $item[$keys[$i]];
}
// Check if the last remaining key exists.
if(array_key_exists($keys[count($keys)-1], $item)) {
// do things
}
You can explode and check the indices of the array.
$array = array(
'fruits' => [
'apple' => 'value',
'orange' => 'value'
],
'vegetables' => [
'onion' => 'value',
'carrot' => 'value'
]);
$string = 'fruits[orange]';
$indexes = (preg_split( "/(\[|\])/", $string));
$first_index= $indexes[0];
$seconnd_index= $indexes[1];
if(isset($array[$first_index][$seconnd_index]))
{
echo "exist";
}
else
{
echo "not exist";
}
DEMO
I have array with this format:
$components = [
[
'name' => 'ADIPIC ACID',
'cas' => '123',
'einecs' => '321'
],
[
'name' => 'ADIPIC ACID/DIMETHY- LAMINOHYDROXY- PROPYL DIETHYLENE- TRIAMINE COPOLYMER',
'cas' => '456',
'einecs' => '654'
]
]
I need to find each name which has a / character, break it and create a new entry in the $components array with cas and einecs being empty string.
Also the first part of the name will have cas and einecs values from the original entry.
Expected array:
$components = [
[
'name' => 'ADIPIC ACID',
'cas' => '123',
'einecs' => '321'
],
[
'name' => 'ADIPIC ACID',
'cas' => '456',
'einecs' => '654'
],[
'name' => 'DIMETHY- LAMINOHYDROXY- PROPYL DIETHYLENE- TRIAMINE COPOLYMER',
'cas' => '',
'einecs' => ''
]
]
How can I do this?
Quite crude I admit and it doesn't account for multiple / characters in a value but it does return the result expected.
foreach( $components as $index=> $arr ){
foreach( $arr as $key => $value ){
if( $key=='name' && strstr( $value, '/' ) ){
list($pre,$post)=explode('/',$value);
$components[$index][$key]=$pre;
$components[]=array('name'=>$post,'cas'=>'','einecs'=>'');
}
}
}
<?php
$components = [
[
'name' => 'ADIPIC ACID',
'cas' => '123',
'einecs' => '321'
],
[
'name' => 'ADIPIC ACID/DIMETHY- LAMINOHYDROXY- PROPYL DIETHYLENE- TRIAMINE COPOLYMER',
'cas' => '456',
'einecs' => '654'
]
];
$new = [];
foreach ($components as &$component) {
if ($items = explode('/', $component['name'])) {
$component['name'] = array_shift($items);
$new = array_merge($new, $items);
}
}
foreach ($new as $item) {
$components[] = ['name' => $item, 'cas' => '', 'einecs' => ''];
}
var_dump($components);
I would try something like this where I use the explode function using the '/' character on the name of each component. Then I'd create a new array of all the new components taking the values of the component being evaluated.
$newComponents = array();
foreach($components as $component) {
foreach(explode('/', $component['name']) as $newComponentName) {
$newComponents[] = array('name' =>$newComponentName,
'cas' => $component['cas'],
'einecs' => $component['einecs']);
}
}
foreach($components as $component)
{
if(strpos($component["name"],"/") !== false){
$temp = explode("/",$component["name"]);
$components[] = new array("name"=>$temp[1], "cas"=>"", "einecs"=>"");
}
}