This seems pretty easy, but I can't figure it out. I have an existing array of objects that was json_decoded. I need to iterate over those objects, append a new array to each, and then put the overall array back together. I can't get the new array to append in the correct place.
function appendToArray($arrayOfObjects) {
$newArray = array();
foreach ($arrayOfObjects as $object) {
echo "<pre>".print_r($object, true)."</pre>";
$newItems = array('item1', 'item2', 'item3');
$moreItems = array('more1', 'more2', 'more3');
$newObject = array();
$newObject["newItems"] = $newItems;
$newObject["moreItems"] = $moreItems;
$rebuiltObject = array();
array_push($rebuiltObject, $object);
$rebuiltObject['new_stuff'] = $newObject;
// $rebuiltObject[0]['new_stuff'] = $newObject;
array_push($newArray, $newObject);
}
return $newArray;
}
Here is an example of one of the objects that I start with (after json_decode of course:
0 => stdClass Object
(
[code] => some code
[first_name] => First
[last_name] => Last
[urls] => stdClass Object
(
[news] => http://www.somesite.com/news
[info] => http://www.somesite.com/info
)
[geo] => stdClass Object
(
[latitude] => 0.0
[longitude] => 0.0
[name] => building name
)
)
When this is done, what I want is this:
0 => stdClass Object
(
[code] => some code
[first_name] => First
[last_name] => Last
[urls] => stdClass Object
(
[news] => http://www.somesite.com/news
[info] => http://www.somesite.com/info
)
[geo] => stdClass Object
(
[latitude] => 0.0
[longitude] => 0.0
[name] => building name
)
[new_stuff] => Array
(
[newItems] => Array
(
[0] => item1
[1] => item2
[2] => item3
)
[moreItems] => Array
(
[0] => more1
[1] => more2
[2] => more3
)
)
)
But what I get is this:
[0] => stdClass Object
(
[code] => some code
[first_name] => First
[last_name] => Last
[urls] => stdClass Object
(
[news] => http://www.somesite.com/news
[info] => http://www.somesite.com/info
)
[geo] => stdClass Object
(
[latitude] => 0.0
[longitude] => 0.0
[name] => building name
)
),
[new_stuff] => Array
(
[newItems] => Array
(
[0] => item1
[1] => item2
[2] => item3
)
[moreItems] => Array
(
[0] => more1
[1] => more2
[2] => more3
)
)
)
Notice how [new_stuff] is outside of the original object. I need to get it inside. Everything else I've tried crashes and I'm totally out of ideas. Can anyone see how I can do this? Thank you!
You solution is one string:
$object->new_stuff = $newObject;
because every $object is object and not array. And adding new property to object is done via -> and not with [].
Full code:
function appendToArray($arrayOfObjects) {
foreach ($arrayOfObjects as $object) {
echo "<pre>".print_r($object, true)."</pre>";
$newItems = array('item1', 'item2', 'item3');
$moreItems = array('more1', 'more2', 'more3');
$newObject = array();
$newObject["newItems"] = $newItems;
$newObject["moreItems"] = $moreItems;
$object->new_stuff = $newObject;
}
return $arrayOfObjects;
}
You can just array_walk and change the object inplace:
array_walk($arrayOfObjects, function(&$item) {
$item->new_stuff = ["newItems" => ['item1', 'item2', 'item3'], etc];
});
Related
I have the following Array.
I am trying to figure out how to create an if statement in the foreach that will set true or false based on if any of the individual indexes has [Customer_Facing_Comments__r]
I am using this code - however, this just tells me if [Customer_Facing_Comments__r] is in the array - which it is, every time. I need to see if it is in each index [0], [1]..etc...and set true or false base on that.
CODE:
foreach($queryResult->records as $record){
if (array_key_exists("Customer_Facing_Comments__r",$record)) {
$test = 'true'; }
else { $test = 'false'; } }
QueryResult Object
(
[queryLocator] =>
[done] => 1
[records] => Array
(
[0] => stdClass Object
(
[Id] => 5003xx0255mhcAAA
[Account] => stdClass Object
(
[Id] => 0010cxx026IwsTAAS
[Name] => xxx
)
[AccountId] => 0010c0xxwsTAAS
[Customer_Facing_Comments__r] => stdClass Object
(
[done] => 1
[queryLocator] =>
[records] => Array
(
[0] => stdClass Object
(
[Id] =>
[Comment__c] => test string
[CreatedDate] => 2021-02-13T00:25:50.000Z
[Trouble_Ticket__c] => 5003x0000255mhcAAA
)
)
[size] => 1
)
[Type] => Service Down
)
[1] => stdClass Object
(
[Id] => 5003x000024Y6TpAAK
[Account] => stdClass Object
(
[Id] => 0010c0cccc6IwsTAAS
[Name] => test
)
[AccountId] => 0010c00cccIwsTAAS
)
Just expose the key in the foreach and use that in your result array $test:
foreach($queryResult->records as $key => $record){
if (isset($record->Customer_Facing_Comments__r)) {
$test[$key] = 'true';
} else {
$test[$key] = 'false';
}
}
I am working with soap responses that contain nested wrappers and whose child(ren) have nested properties.
I am trying to flatten these response to:
remove the wrappers
flatten the children
maintain the individual children (dimensions)
I am currently working with the following that achieves #1 and #3 however it does not flatten the inner children. Note that $this->response is converted from a stdClass to Array before being flattened.
How can I also flatten down the inner nested child elements?
private function toArray()
{
$this->response = json_decode(json_encode($this->response), true);
return $this;
}
private function flatten($array = null)
{
if (is_null($array)) {
$array = $this->response;
}
if (is_array($array)) {
foreach ($array as $k => $v) {
if (count($v) == 1 && is_array($v)) {
return $this->flatten($v);
}
if (isset($v[0])) {
$this->response = $v;
return $this;
}
unset($this->response);
$this->response[] = $v;
return $this;
}
}
}
...which will transform this:
stdClass Object
(
[ArrayOfDevice] => stdClass Object
(
[Device] => Array
(
[0] => stdClass Object
(
[NamedElement] => stdClass Object
(
[Element] => stdClass Object
(
[ElementType] => DEVICE
[id] => Device1ID
)
[name] => Device1
)
[hostName] => Device1.hostname
[ipAddress] => Device1.ip
[location] => location1
[modelName] =>
[modelNumber] =>
[parentID] => xxxYYY
[serialNumber] => 123456789
)
[1] => stdClass Object
(
[NamedElement] => stdClass Object
(
[Element] => stdClass Object
(
[ElementType] => DEVICE
[id] => Device2ID
)
[name] => Device2
)
[hostName] => Device2.hostname
[ipAddress] => Device2.ip
[location] => location1
[modelName] =>
[modelNumber] =>
[parentID] => xxxYYY
[serialNumber] => 987654321
)
)
)
)
...to this:
Array
(
[0] => Array
(
[NamedElement] => Array
(
[Element] => Array
(
[ElementType] => DEVICE
[id] => Device1ID
)
[name] => Device1
)
[hostName] => Device1.hostname
[ipAddress] => Device1.ip
[location] => location1
[modelName] =>
[modelNumber] =>
[parentID] => xxxYYY
[serialNumber] => 123456789
)
[1] => Array
(
[NamedElement] => Array
(
[Element] => Array
(
[ElementType] => DEVICE
[id] => Device2ID
)
[name] => Device2
)
[hostName] => Device2.hostname
[ipAddress] => Device2.ip
[location] => location1
[modelName] =>
[modelNumber] =>
[parentID] => xxxYYY
[serialNumber] => 987654321
)
)
...but I'd prefer:
Array
(
[0] => Array
(
[ElementType] => DEVICE
[id] => Device1ID
[name] => Device1
[hostName] => Device1.hostname
[ipAddress] => Device1.ip
[location] => location1
[modelName] =>
[modelNumber] =>
[parentID] => xxxYYY
[serialNumber] => 123456789
)
[1] => Array
(
[ElementType] => DEVICE
[id] => Device2ID
[name] => Device2
[hostName] => Device2.hostname
[ipAddress] => Device2.ip
[location] => location1
[modelName] =>
[modelNumber] =>
[parentID] => xxxYYY
[serialNumber] => 987654321
)
)
...and in the case of a single item being returned, this:
stdClass Object
(
[ArrayOfAlarm] => stdClass Object
(
[Alarm] => stdClass Object
(
[Element] => stdClass Object
(
[ElementType] => ALARM
[id] => Alarm1ID
)
[activeTime] =>
[AlarmSeverity] =>
[AlarmState] =>
[description] =>
[deviceID] =>
[recommendedAction] =>
[resolvedTime] =>
[sensorID] =>
)
)
)
...to this:
Array
(
[0] => Array
(
[Element] => Array
(
[ElementType] => ALARM
[id] => Alarm1ID
)
[activeTime] =>
[AlarmSeverity] =>
[AlarmState] =>
[description] =>
[deviceID] =>
[recommendedAction] =>
[resolvedTime] =>
[sensorID] =>
)
)
...but I'd prefer:
Array
(
[0] => Array
(
[ElementType] => ALARM
[id] => Alarm1ID
[activeTime] =>
[AlarmSeverity] =>
[AlarmState] =>
[description] =>
[deviceID] =>
[recommendedAction] =>
[resolvedTime] =>
[sensorID] =>
)
)
You can flatten a single of your items with the following function:
function flatten_item($array)
{
$result = [];
foreach ($array as $k => $v) {
if (is_array($v)) {
$result = array_merge($result, $this->flatten_item($v));
} else {
$result[$k] = $v;
}
}
return $result;
}
When you have an array of results, you can pass this function as the callback to array_map. Only the relevant portion of the code:
if (isset($v[0])) {
$this->response = array_map([$this, 'flatten_item'], $v);
return $this;
}
// Convert single result to an array
$this->response = [$this->flatten_item($v)];
return $this;
Since the response (so far) always has the same structure, you could extract the payload without using recursion, which allows you to also remove the foreach in the flatten function:
function flatten()
{
// Remove outer wrappers [ArrayOfX][X] by extracting the value
$payload = current(current($this->response));
if (isset($payload[0])) {
$this->response = array_map([$this, 'flatten_item'], $payload);
} else {
$this->response = [$this->flatten_item($payload)];
}
return $this;
}
The function found here does just what you want, with a slight modification (commented out concatination of parent keys): https://gist.github.com/kohnmd/11197713#gistcomment-1895523
function flattenWithKeys(array $array, $childPrefix = '.', $root = '', $result = array()) {
foreach($array as $k => $v) {
if(is_array($v) || is_object($v)) $result = flattenWithKeys( (array) $v, $childPrefix, $root . $k . $childPrefix, $result);
else $result[ /*$root .*/ $k ] = $v;
}
return $result;
}
Letting $object equal your provided object, use as follows:
$array = json_decode(json_encode($object), true);
$result =[];
foreach( $array['ArrayOfDevice']['Device'] as $key => $value ){
$result[$key] = flattenWithKeys($value);
}
print_r($result);
Output:
Array
(
[0] => Array
(
[ElementType] => DEVICE
[id] => Device1ID
[hostName] => Device1.hostname
[ipAddress] => Device1.ip
[location] => location1
[modelName] =>
[modelNumber] =>
[parentID] => xxxYYY
[serialNumber] => 123456789
)
[1] => Array
(
[ElementType] => DEVICE
[id] => Device2ID
[name] => Device2
[hostName] => Device2.hostname
[ipAddress] => Device2.ip
[location] => location2
[modelName] =>
[modelNumber] =>
[parentID] => xxxYYY
[serialNumber] => 987654321
)
)
See it run here: http://sandbox.onlinephpfunctions.com/code/851e93389b993a0e44c1e916291dc444f47047d3
I have JSON arrays of objects. I am trying to sort an array using usort. I want to use value field from field_listing_order. It sorted using value. I am missing something but not able to figure it out. please review the code. Thanks!
stdClass Object
(
[node_title] => abc
[nid] => 2281
[field_api_order_value] => 201
[field_node_entity_type] => node
[_data] => Array
(
[nid] => Array
(
[entity_type] => node
[entity] => stdClass Object
(
[title] => abc
[field_listing_order] => Array
(
[und] => Array
(
[0] => Array
(
[value] => 8
[format] =>
[safe_value] => 8
)
)
)
)
)
)
)
stdClass Object
(
[node_title] => abc
[nid] => 2243
[field_api_order_value] => 204
[field_node_entity_type] => node
[_data] => Array
(
[nid] => Array
(
[entity_type] => node
[entity] => stdClass Object
(
[title] => abc
[field_listing_order] => Array
(
[und] => Array
(
[0] => Array
(
[value] => 3
[format] =>
[safe_value] => 3
)
)
)
)
)
)
) stdClass Object
(
[node_title] => abc
[nid] => 2431
[field_api_order_value] => 242
[field_node_entity_type] => node
[_data] => Array
(
[nid] => Array
(
[entity_type] => node
[entity] => stdClass Object
(
[title] => abc
[field_listing_order] => Array
(
[und] => Array
(
[0] => Array
(
[value] => 1
[format] =>
[safe_value] => 1
)
)
)
)
)
)
)
and So on ...
foreach ($view->result as $result) {
$node = $result->_data['nid']['entity'];
$listing_order = $node->field_listing_order[LANGUAGE_NONE][0];
.....
// code goes here and it works well. sorting issue
}
usort ($node->field_listing_order[LANGUAGE_NONE][0], function($a, $b){
return strcmp($a->value, $b->value);
}); ?>
If you need to sort all the nodes using the field_listing_order value, you need to compare the values along the full path, from the first object to the value:
usort($view->result, function($a, $b) {
$la = $a->_data['nid']['entity']->field_listing_order[LANGUAGE_NONE][0]['value'];
$lb = $b->_data['nid']['entity']->field_listing_order[LANGUAGE_NONE][0]['value'];
return $la - $lb ;
});
In this case $a and $b are two different nodes which could be compared. That why you should compare the field_listing_order's value of these nodes. The answer is working with $la- $lb
I'm trying to group the arrays of a query, using the PHP foreach loop, to a group of objects without sub objects. But I'm not getting it, I've tried it in several ways. I'm using the following loop with foreach:
public function array_to_object($array)
{
$obj = new stdClass;
foreach($array as $k => $v) {
if(is_array($v)){
$obj->{$k} = $this->array_to_object($v); //RECURSION
} else {
$obj->{$k} = $v;
}
}
return $obj;
}
$users = $this->array_to_object($users);
print_r((array)$users);
I have this result:
Array
(
[0] => stdClass Object
(
[_id] => 12
[username] => lucaspedro
[first_name] => Lucas
[user_role] => stdClass Object
(
[ur_name] => Admin
)
)
[1] => stdClass Object
(
[_id] => 32
[username] => joaosilva
[first_name] => Joao
[user_role] => stdClass Object
(
[ur_name] => Member
)
)
)
But I need this result:
Array
(
[0] => stdClass Object
(
[_id] => 12
[username] => lucaspedro
[first_name] => Lucas
[ur_name] => Admin
)
[1] => stdClass Object
(
[_id] => 32
[username] => joaosilva
[first_name] => Joao
[ur_name] => Member
)
)
A simple foreach can do the trick for you.
foreach($array as $k=>$v){
$array[$k]->ur_name = $v->user_role->ur_name;
unset($array[$k]->user_role);
}
print_r($array);
I want to merge the 2 arrays of objects based on the 'id' field of Array1 and the 'itemVendorCode' of Array2. I also wanted to remove from the resulting arrays of object anything that didn't match.
Array1:
Array
(
[0] => stdClass Object
(
[id] => 10-423-1176
[qty] => 2
[price] => 12.6
)
[1] => stdClass Object
(
[id] => 89-575-2354
[qty] => 24
[price] => 230.35
)
[2] => stdClass Object
(
[id] => 89-605-1250
[qty] => 2
[price] => 230.35
)
)
Array2:
Array
(
[0] => Item Object
(
[internalId] => 14062
[itemVendorCode] => 89-605-1250
)
[1] => Item Object
(
[internalId] => 33806
[itemVendorCode] => 89-575-2354
)
[2] => Item Object
(
[internalId] => 64126
[itemVendorCode] => 26-295-1006
)
)
I was able to solve this by this code:
$indexed = array();
foreach($itemsArray as $value) {
$indexed[$value->itemVendorCode] = $value;
}
$results = array();
foreach($vendorItems as $obj) {
$value = $indexed[$obj->id];
if (isset($value)) {
foreach($value as $name => $val) {
$obj->$name = $val;
array_push($results, $obj);
}
}
}
print_r($results);
credits to the original poster. I just modified it a bit,
I was able to get the result like this:
Array
(
[0] => stdClass Object
(
[id] => 10-423-1176
[qty] => 2
[price] => 12.6
[internalId] => 2035
[itemVendorCode] => 10-423-1176
)
[1] => stdClass Object
(
[id] => 10-423-1176
[qty] => 2
[price] => 12.6
[internalId] => 2035
[itemVendorCode] => 10-423-1176
)
[2] => stdClass Object
(
[id] => 14-102-1010
[qty] => 16
[price] => 3.2
[internalId] => 57033
[itemVendorCode] => 14-102-1010
)
)
I think you will have to use array_map function which provides you a callback function to execute on array(s).
In the callback function:
- declare your array1
- foreach the second array
- set an if statement to check that the current iteration with the id value matches the itemVendorCode of the array2 and return it
something like this:
// You have to specify to PHP to use a local copy of your $array2 to works with it into your callback
$cb = function ($obj1) use ($array2)
{
// you foreach this array
foreach ($array2 as $obj2) {
// if the value of id matches itemVendorCode
if ($obj1->id === $obj2->itemVendorCode) {
// you return the id
return $obj->id;
}
}
};
// this function will fill a new array with all returned data
$mergedArray = array_map($cb, $array1);
This code is a sample but doesn't provide you, your needled solution, try to update it to do what you exactly want ;)