how to use explode for an array of objects - php

I have an array like that:
array(5) {
["code"]=>
int(1)
["messageError"]=>
string(27) "La typologie est incorrecte"
["model"]=>
string(3) "lot"
["grp_regles"]=>
array(1) {
[0]=>
array(1) {
[0]=>
array(3) {
["champ"]=>
string(21) "lot_surface_habitable"
["comparaison"]=>
string(7) "between"
["valeurAttendue"]=>
array(2) {
[0]=>
int(16)
[1]=>
int(40)
}
}
}
}
["prerequis"]=>
array(2) {
[0]=>
array(3) {
["champ"]=>
string(6) "typ_id"
["comparaison"]=>
string(1) "="
["valeurAttendue"]=>
int(1)
}
[1]=>
array(3) {
["champ"]=>
string(22) "tranche.fus.fup.fup_id"
["comparaison"]=>
string(1) "="
["valeurAttendue"]=>
int(1)
}
}
}
I want to do a foreach in "prerequis":
$modelRetrieve = $this->retrieveModel($model);
$modelFind = $modelRetrieve::find($id);
$arrayError=[];
$query = '';
$path = storage_path() . "/json/controle.json";
$json = file_get_contents($path);
foreach (json_decode($json,true) as $key => $value) {
$test = true;
var_dump($value);
if($value['model'] === $model ){
foreach ($value['prerequis'] as $key => $value2) {
if( $test && $modelFind[$value2['champ']] == (int)$value2["valeurAttendue"] )
{
$test = true;
}
}
}
}
I need in second foreach to use in $value2['champ'] where $value2['champ'] is "tranche.fus.fup_id. So I need to explode that to have ['tranche']['fus']['fup_id'].
How to use explode with that ?
thanks everyone :)

you can use laravel data_get helper:
data_get($value2, $value2['champ'])

To nest the $segments of the string starting with the innermost item of the result, we have to array_reverse() the $segments so we can loop over it and wrap each iteration's result with another array level in the next iteration until we looped through the whole $segments array.
$exploded = array_reduce(array_reverse(explode('.', $value2['champ'])), function($res, $segment) {
return [ $segment => $res ];
}, []);

Related

How to iterate through elements of an array up until its seventh

I have a function that iterates throughout an array
function ($data)
{
$path = $data->data->data->clicks;
foreach ($path as $key => $item){
if ($key >= 0) {
$array[] = $item->clicks;
}
}
return json_encode($array);
}
I try to make it iterate up until its seventh key, I have written an if statement but I am quite new to this and I don't know how to do this.
If it help the array structure look like this:
["data"]=>
object(stdClass)#212 (3) {
["status_code"]=>
int(200)
["data"]=>
object(stdClass)#211 (3) {
["days"]=>
int(30)
["total_clicks"]=>
int(6)
["clicks"]=>
array(30) {
[0]=>
object(stdClass)#215 (2) {
["clicks"]=>
int(0)
["day_start"]=>
int(1466395200)
}
[1]=>
object(stdClass)#216 (2) {
["clicks"]=>
int(0)
["day_start"]=>
int(1466308800)
}
[2]=>
object(stdClass)#217 (2) {
["clicks"]=>
int(0)
["day_start"]=>
int(1466222400)
}
Just add a variable that counts up and break when it's greater than 7
$num_loops = 0;
foreach ($path as $key => $item){
$num_loops++;
if($num_loops > 7) break;
if ($key >= 0) {
$array[] = $item->clicks;
}
}
The short way by using array_map and array_slice functions(no loops, no if conditions):
$path = $data->data->data->clicks;
$clicks = array_map(function($o){
return $o->clicks;
}, array_slice($path, 0, 7));

PHP: Combining data with a shared key from a single array into new array

I have this array:
array(5) {
[0]=>
array(4) {
["productCode"]=>
string(4) "X001"
["productUPC"]=>
string(3) "261"
["productTextSeq"]=>
string(1) "1"
["productTxtVal"]=>
string(5) "Text1"
}
[1]=>
array(4) {
["productCode"]=>
string(4) "X001"
["productUPC"]=>
string(3) "261"
["productTextSeq"]=>
string(1) "2"
["productTxtVal"]=>
string(5) "Text2"
}
[2]=>
array(4) {
["productCode"]=>
string(4) "X001"
["productUPC"]=>
string(3) "261"
["productTextSeq"]=>
string(1) "3"
["productTxtVal"]=>
string(5) "Text3"
}
[3]=>
array(4) {
["productCode"]=>
string(4) "X002"
["productUPC"]=>
string(3) "262"
["productTextSeq"]=>
string(1) "1"
["productTxtVal"]=>
string(5) "Text1"
}
[4]=>
array(4) {
["productCode"]=>
string(4) "X002"
["productUPC"]=>
string(3) "262"
["productTextSeq"]=>
string(1) "2"
["productTxtVal"]=>
string(5) "Text2"
}
}
With the above input, I want the output array to look like this:
array(2) {
[0]=>
array(3) {
["productCode"]=>
string(4) "X001"
["productUPC"]=>
string(3) "261"
["productTxtVal"]=>
string(17) "Text1 Text2 Text3"
}
[1]=>
array(3) {
["productCode"]=>
string(4) "X002"
["productUPC"]=>
string(3) "262"
["productTxtVal"]=>
string(11) "Text1 Text2"
}
}
The resulting array does not need the productTextSeq key, just the combined values of productTextVal, when the productCode is the same. I've searched SO for examples of this but it seems every example I've found are based on multiple input arrays. I know I can brute force this with nested foreach functions but would love a more elegant solution.
I ended up just doing it the brute force method, here is my solution if anyone's interested:
$productData = array();
$sortedData = array();
$comments = '';
$saveKey = '';
$appendComment = false;
$idx = 0;
foreach ($data as $key=>$value) {
foreach ($value as $k=>$v) {
if ($k == 'productCode') {
if ($v == $saveKey) {
$appendComment = true;
} else {
$appendComment = false;
$saveKey = $v;
if ($idx !== 0) { // Don't write to array on first iteration!
$productData['productTxtVal'] = $comments;
$sortedData[] = $productData;
}
}
}
if ($k == 'productTxtVal') {
if ($appendComment == true) {
$comments .= ' ' . trim($v);
} else {
$comments = trim($v);
}
}
}
$productData = $value;
$idx++;
}
Not "elegant" but it works. I also have a check after this logic in case only one productCode is in the original array, as it won't be written to the $sortedData array since the key never changes.
The following code assumes you control the contents of the original data array (due to risk of injection using extract() function) and that no 2 items with the same productCode have the same productTextSeq.
$products = [];
foreach ($data as $item) {
// extract contents of item array into variables
extract($item);
if (!isset($products[$productCode])) {
// create product array with code, upc, text as array
$products[$productCode] = compact('productCode', 'productUPC') + ['productTxtVal' => []];
}
// add text value to array with sequence as index
$products[$productCode]['productTxtVal'][$productTextSeq] = $productTxtVal;
}
$products = array_values( // ignore array keys
array_map(function($product) {
ksort($product['productTxtVal']); // sort text as array by index/ sequence
$product['productTxtVal'] = implode(' ', $product['productTxtVal']); // implode into string
return $product;
}, $products)
);
You can run the code here: https://repl.it/BWQL

create php array using simpleXMLobject

I'm trying to get this array ($resdata) with object(SimpleXMLElement) into a php array:
$resdata =
array(59) {
[0]=> ...
[10]=> object(SimpleXMLElement)#294 (28) {
["reservation_id"]=> string(7) "8210614"
["event_id"]=> string(6) "279215"
["space_reservation"]=> array(2) {
[0]=> object(SimpleXMLElement)#344 (9) {
["space_id"]=> string(4) "3760"
["space_name"]=> string(9) "205"
["formal_name"]=> string(33) "Center" }
[1]=> object(SimpleXMLElement)#350 (9) {
["space_id"]=> string(4) "3769"
["space_name"]=> string(9) "207"
["formal_name"]=> string(32) "Right" } } }
}
I've tried:
$res = (array)$resdata;
$reservation = $res['reservation'];
$result = array();
foreach ($reservation as $key => $value){
$res = array($value);
$spid = $res[0]->space_reservation->space_id;
echo $value->event_id."<br />";
echo $spid."<br />";
}
This only outputs the first space_id and I need to get all the space_ids within "space_reservation" array. Not all records will have multiple space_ids. Any help pointing me in the right direction is appreciated. Not sure if I should use xpath but I need to re-write my foreach statement regardless.
I was hoping to be able to literally convert all references to "object(SimpleXMLElement)#_ (#)" to "array(#)"
[10]=> array (28) {
["reservation_id"]=> string(7) "8210614"
["event_id"]=> string(6) "279215"
["space_reservation"]=> array(2) {
[0]=> array (9) {
["space_id"]=> string(4) "3760"
["space_name"]=> string(9) "205"
["formal_name"]=> string(33) "Center" }
[1]=> array (9) {
["space_id"]=> string(4) "3769"
["space_name"]=> string(9) "207"
["formal_name"]=> string(32) "Right" } } }
}
the function in my cakephp 1.3 controller is this:
$xml = simplexml_load_string($string);
$this->data['events']= $xml->children();
$resdata = $this->data['events'];
$this->set('resdata',$resdata);
I think this should do what you are looking for:
foreach ($resdata as $res) {
echo $res->event_id . '<br />';
foreach ($res->space_reservation as $reservation) {
echo $reservation->space_id . '<br />';
}
}
Googled it and found a general solution for any SimpleXMLElement to array conversion:
function xml2array($xml) {
$arr = array();
foreach ($xml as $element) {
$tag = $element->getName();
$e = get_object_vars($element);
if (!empty($e)) {
$arr[$tag] = $element instanceof SimpleXMLElement ? xml2array($element) : $e;
}
else {
$arr[$tag] = trim($element);
}
}
return $arr;
}

PHP Error: Undefined offset error within foreach loop

I have a csv file which I am trying to turn into a different structured array. First, I turn it into an array named all_data() constructed like this:
$data = file_get_contents($id . '.csv');
$data_array = explode("\n", $data);
foreach($data_array AS $data){
$all_data[] = explode("\t", $data);
}
results look like this:
array(5) {
[0]=>
array(2) {
[0]=>
string(10) "2012-11-14"
[1]=>
string(2) "10"
}
[1]=>
array(2) {
[0]=>
string(10) "2012-11-14"
[1]=>
string(2) "10"
}
[2]=>
array(2) {
[0]=>
string(10) "2012-11-14"
[1]=>
string(2) "10"
}
[3]=>
array(2) {
[0]=>
string(10) "2012-11-14"
[1]=>
string(2) "10"
}
[4]=>
array(1) {
[0]=>
string(0) ""
}
}
And then I turn it into im_arr() with the following code:
foreach($all_data as $key => $value){
$im_arr[$key][$value[0]] = $value[1];
}
The results:
array(5) {
[0]=>
array(1) {
["2012-11-14"]=>
string(2) "10"
}
[1]=>
array(1) {
["2012-11-14"]=>
string(2) "10"
}
[2]=>
array(1) {
["2012-11-14"]=>
string(2) "10"
}
[3]=>
array(1) {
["2012-11-14"]=>
string(2) "10"
}
[4]=>
array(1) {
[""]=>
NULL
}
}
And then, finally another foreach loop gives me the results I am looking for:
foreach ($im_arr as $val) {
foreach ($val as $key => $val2) {
$im_data[$key]=$val2;
}
}
With the result for im_data() being:
array(2) {
["2012-11-14"]=>
string(2) "10"
[""]=>
NULL
}
Which would be perfect, since the array im_data() is exactly what I would like to get out of all_data(). However, when I am trying to put this code in another part of the program it doesn't work, and I am thinking it might be because of the warnings I receive:
"PHP Notice: Undefined offset: 1 in ... on line 93"
Line 93 corresponds to this line:
$im_arr[$key][$value[0]] = $value[1];
Here is the complete part of the code:
$all_data = array();
$im_arr=array();
$data = file_get_contents($id . '.csv');
$data_array = explode("\n", $data);
foreach($data_array AS $data){
$all_data[] = explode("\t", $data);
}
foreach($all_data as $key => $value){
$im_arr[$key][$value[0]] = $value[1]; //the line for the error
}
$im_data=array();
foreach ($im_arr as $val) {
foreach ($val as $key => $val2) {
$im_data[$key]=$val2;
}
}
var_dump($im_data);
I know there are many many questions posted for this same error, but I couldn't figure out the problem with this particular piece of code.
This is the problem:
[4]=>
array(1) {
[0]=>
string(0) ""
}
Just check that the data is set, and isn't empty before adding them to $im_arr:
foreach ($all_data as $key => $value) {
if (isset($value[0]) && isset($value[1]) && !empty($value[0]) && !empty($value[1])) {
$im_arr[$key][$value[0]] = $value[1];
}
}
For every foreach i would pre-check if the first argument is an array
For instance ;
//Just add line below for every foreach (and add any required else statement if needed)
if(is_array($im_arr))
foreach ($im_arr as $val) {
if(is_array($val))
foreach ($val as $key => $val2) {
$im_data[$key]=$val2;
}
}

PHP sequential foreach

Guys i've got an array thats like this:
array(3) {
[2]=>
array(1) {
["name"]=>
array(2) {
[0]=>
string(13) "row1"
[1]=>
string(13) "row3"
}
}
[5]=>
array(1) {
["name"]=>
array(2) {
[0]=>
string(15) "row1"
[1]=>
string(15) "row3"
}
}
[3]=>
array(1) {
["name"]=>
array(2) {
[0]=>
string(13) "row1"
[1]=>
string(13) "row3"
}
}
What i want to achieve is make foreach loop the 0 elements (row1) and then loop through 1 (row3) and go on like this. Is there a way to do that?
You could try to rebuild the array:
$rows = array();
foreach($array as $subarray)
foreach($subarray as $key => $value)
$rows[$key][] = $value;
At this point al the same subelements from the array are together in a new array, and now you can easy loop over a subelement:
foreach($rows as $key => $value)
echo 'processing row: ' . $key ' with value ' . $value;
I found a different approach to this problem, the JvdBeg solution is working wonderful, but if someone is stuck in a similar situations, this is how i did it:
$key = key($arr);
$keys = array_keys($arr);
for ($i=0;$i<sizeof($arr[$key]['index']);$i++) {
for($k=0;$k<sizeof($arr);$k++) {
$key = $keys[$k];
echo "\n";
}
}

Categories