PHP: SOAP response sort results - php

I'm trying to sort the results by ROOMPRICE of a soap response :
stdClass Object (
[GetHotelsResult] => stdClass Object (
[SEARCH_RESPONSE] => Array (
[0] => stdClass Object (
[HOTELNAME] => Hotel1
[ROOMNAME] => Room2
[ROOMPRICE] => 144.50
)
[1] => stdClass Object (
[HOTELNAME] => Hotel1
[ROOMNAME] => Room1
[ROOMPRICE] => 231.10
)
[2] => stdClass Object (
[HOTELNAME] => Hotel1
[ROOMNAME] => Room3
[ROOMPRICE] => 94.00
)
)
)
);
I've made many solutions, but they didn't work...
MY ACTUAL CODE:
$sClient = new SoapClient($wsdl, array('trace' => 1));
$response = $sClient->GetHotels($data);
$ghdata = $sClient->__getLastResponse();
$doc = new DOMDocument();
$doc->loadXML($ghdata);
$x = $doc->documentElement;
$rooms = $x->getElementsByTagName( "SEARCH_RESPONSE" );
foreach( $rooms as $SEARCH_RESPONSE )
{ // show results

Assuming $response is your outer stdClass object, I guess you're getting and error like that:
Warning: usort() expects parameter 1 to be array, object given in ...
This is because usort works with array and not objects. What you actually want to sort is a SEARCH_RESPONSE array. Also, pay attention that elements in this array are stdClass objects themselves, so you have to use $a->{$key} notation instead of []:
function build_sorter($key) {
return function ($a, $b) use ($key) {
// pay attention to `{$key}` notation
return strnatcmp($a->{$key}, $b->{$key});
};
}
// Get array to sort
usort($response->GetHotelsResult->SEARCH_RESPONSE, build_sorter('ROOMPRICE'));
foreach ($response->GetHotelsResult->SEARCH_RESPONSE as $item) {
echo $item->ROOMNAME . ', ' . $item->ROOMPRICE . "\n";
}

Related

Could not sort json object by same key using PHP

I am trying to sort json object by same key and merge the value part using PHP but not getting the result as expected. My code is below:
$customArr=[{"attribute_code":"budget","value":"141"},{"attribute_code":"restaurants","value":"166"},{"attribute_code":"food_type","value":"172"},{"attribute_code":"budget","value":"142"},{"attribute_code":"restaurants","value":"168"},{"attribute_code":"food_type","value":"173"},{"attribute_code":"budget","value":"143"},{"attribute_code":"restaurants","value":"170"},{"attribute_code":"food_type","value":"173"},{"attribute_code":"budget","value":"162"},{"attribute_code":"restaurants","value":"171"},{"attribute_code":"food_type","value":"172"}]
function sortByName($a, $b){
$a = $a['attribute_code'];
$b = $b['attribute_code'];
if ($a == $b) return 0;
return ($a < $b) ? -1 : 1;
}
usort($customArr, 'sortByName');
Here I need if attribute_code is same then push the respective value into one array and also the duplicate value should not be there. The expected result is given below.
[{"attribute_code":"budget","value":[141,142,143,162]},{}.....]
But in my case the expected result not coming.
Using array_reduce() you can try it. array_reduce() callback takes two arguments, who's first argument is the old/previous iteration value and second argument is the current iteration value/element.
So using this function we can holds our current iteration values to the previous iteration value (total values).
array_reduce() iteratively reduce the array to a single value using a callback function.
$customArr = json_decode('[{"attribute_code":"budget","value":"141"},{"attribute_code":"restaurants","value":"166"},{"attribute_code":"food_type","value":"172"},{"attribute_code":"budget","value":"142"},{"attribute_code":"restaurants","value":"168"},{"attribute_code":"food_type","value":"173"},{"attribute_code":"budget","value":"143"},{"attribute_code":"restaurants","value":"170"},{"attribute_code":"food_type","value":"173"},{"attribute_code":"budget","value":"162"},{"attribute_code":"restaurants","value":"171"},{"attribute_code":"food_type","value":"172"}]', true);
$data = array_reduce($customArr, function ($acc, $new) {
if (isset($acc[$new['attribute_code']])) {
$old_value = $acc[$new['attribute_code']]['value'];
$acc[$new['attribute_code']]['value'] = array_unique(is_array($old_value) ? array_merge($old_value, [$new['value']]) : [$old_value, $new['value']]);
} else {
$acc[$new['attribute_code']] = $new;
}
return $acc;
}, []);
ksort($data);
echo '<pre>', json_encode(array_values($data));
Working demo.
At the moment you are just sorting the entries according to the attribute_code and doing nothing about merging the data items.
This code creates a new output array (keyed it by the attribute_code), if the code is already there it adds the value into the list of existing values, if not it adds a new item in, creating the value as an array (with the first item in). Lastly it uses ksort() to sort the items.
If you don't need these keys, then array_values() will give you a plain array (as in the output)...
$json='[{"attribute_code":"budget","value":"141"},{"attribute_code":"restaurants","value":"166"},{"attribute_code":"food_type","value":"172"},{"attribute_code":"budget","value":"142"},{"attribute_code":"restaurants","value":"168"},{"attribute_code":"food_type","value":"173"},{"attribute_code":"budget","value":"143"},{"attribute_code":"restaurants","value":"170"},{"attribute_code":"food_type","value":"173"},{"attribute_code":"budget","value":"162"},{"attribute_code":"restaurants","value":"171"},{"attribute_code":"food_type","value":"172"}]';
$customArr = json_decode($json, true);
$output = [];
foreach ( $customArr as $attribute ) {
if ( isset ( $output[$attribute['attribute_code']])) {
$output[$attribute['attribute_code']]['value'][] = $attribute['value'];
}
else {
$output[$attribute['attribute_code']] = ["attribute_code"=>$attribute['attribute_code'],
"value"=> [$attribute['value']]];
}
}
// Make sure values are unique
foreach ( $output as $code => $value ){
$output[$code]['value'] = array_unique($output[$code]['value']);
}
ksort($output);
print_r(array_values($output));
gives...
Array
(
[0] => Array
(
[attribute_code] => budget
[value] => Array
(
[0] => 141
[1] => 142
[2] => 143
[3] => 162
)
)
[1] => Array
(
[attribute_code] => food_type
[value] => Array
(
[0] => 172
[1] => 173
)
)
[2] => Array
(
[attribute_code] => restaurants
[value] => Array
(
[0] => 166
[1] => 168
[2] => 170
[3] => 171
)
)
)
You have a JSON string, not an array.
$jsonString = '[{"attribute_code":"budget","value":"141"},{"attribute_code":"restaurants","value":"166"},{"attribute_code":"food_type","value":"172"},{"attribute_code":"budget","value":"142"},{"attribute_code":"restaurants","value":"168"},{"attribute_code":"food_type","value":"173"},{"attribute_code":"budget","value":"143"},{"attribute_code":"restaurants","value":"170"},{"attribute_code":"food_type","value":"173"},{"attribute_code":"budget","value":"162"},{"attribute_code":"restaurants","value":"171"},{"attribute_code":"food_type","value":"172"}]';
$customArr = json_decode($jsonString, true);
function sortByName($a, $b)
{
$a = $a['attribute_code'];
$b = $b['attribute_code'];
if ($a == $b) return 0;
return ($a < $b) ? -1 : 1;
}
usort($customArr, 'sortByName');
The similar solution as above, but a little different using a temp variable and in a single iteration:
<?php
$str='[{"attribute_code":"budget","value":"141"},{"attribute_code":"restaurants","value":"166"},{"attribute_code":"food_type","value":"172"},{"attribute_code":"budget","value":"142"},{"attribute_code":"restaurants","value":"168"},{"attribute_code":"food_type","value":"173"},{"attribute_code":"budget","value":"143"},{"attribute_code":"restaurants","value":"170"},{"attribute_code":"food_type","value":"173"},{"attribute_code":"budget","value":"162"},{"attribute_code":"restaurants","value":"171"},{"attribute_code":"food_type","value":"172"}]';
$arr = json_decode($str,true);
$temp = $result= [];
foreach($arr as $key=>$customer){
if(in_array($customer['attribute_code'], $temp)){
$index=array_search($customer['attribute_code'],$temp);
if(!in_array($customer['value'],$result[$index]['value'])){
$result[$index]['value'][]=$customer['value'];
}
}else {
$temp[]=$customer['attribute_code'];
$result[]=[
'attribute_code'=>$customer['attribute_code'],
'value'=>[$customer['value']]
];
}
}
unset($temp);
print_r($result);
echo json_encode($result);
?>
Result :
Array
(
[0] => Array
(
[attribute_code] => budget
[value] => Array
(
[0] => 141
[1] => 142
[2] => 143
[3] => 162
)
)
[1] => Array
(
[attribute_code] => restaurants
[value] => Array
(
[0] => 166
[1] => 168
[2] => 170
[3] => 171
)
)
[2] => Array
(
[attribute_code] => food_type
[value] => Array
(
[0] => 172
[1] => 173
)
)
)
JSON ENCODED RESPONSE
[{"attribute_code":"budget","value":["141","142","143","162"]},{"attribute_code":"restaurants","value":["166","168","170","171"]},{"attribute_code":"food_type","value":["172","173"]}]

PHP - how to search ID and display its value in a object

Hi I have an array of object like this
$json = json_decode($featureJson);
//which returns below
Array
(
[0] => stdClass Object
(
[productID] => 1
[productName] => Toyo
[assessments] => Array
(
[0] => stdClass Object
(
[answer] => Yes
)
[1] => stdClass Object
(
[answer] => Yes
)
...
)
)
[1] => stdClass Object
(
[productID] => 2
[productName] => Maze
[assessments] => Array
(
[0] => stdClass Object
(
[answer] => Yes
)
[1] => stdClass Object
(
[answer] => Yes
)
...
)
)
)
and I have another array that needs to match the ID of $json(Array of Objects) and return its productName.
$string = "1,2|2,1";
$IdArray = explode('|', $string);
$foo = '';
foreach ($IdArray as $item) {
$foo .= '{' . $item . '},';
}
echo $foo;
$foo return {1,2},{2,1} and I match $json so will display - {Toyo,Maze},{Maze,Toyo}, how can I do that? I have some hint using array_map()
but still got no idea to match in objects.
It's easier if you separate an array for the names first.
<?php
$featureJson = '[{"productID":1,"productName":"Toyo","assessments":[{"answer":"Yes"},{"answer":"No"}]},{"productID":2,"productName":"Maze","assessments":[{"answer":"Yes"},{"answer":"Yes"}]}]';
$json = json_decode($featureJson);
// Make an array of names
$names = [];
foreach($json as $products){
$names[$products->productID] = $products->productName;
};
$string = "1,2|2,1";
$IdArray = explode('|', $string);
$foo = [];
foreach ($IdArray as $ids) {
$ids = explode(',',$ids);
$fooItem = [];
foreach($ids as $id){
$fooItem[] = $names[$id];
}
$foo[]= '{' . implode(',',$fooItem) . '}'; }
echo implode(',',$foo);
Result:
{Toyo,Maze},{Maze,Toyo}
Check here

group array of php objects and sum by object key

I have an array of php objects that looks something like this:
Array
(
[0] => stdClass Object
(
[order_id] => 1513
[order_total] => 12500.00
[sales_rep] => Doe_John
)
[1] => stdClass Object
(
[order_id] => 1046
[order_total] => 3300.00
[sales_rep] => Doe_John
)
[2] => stdClass Object
(
[order_id] => 337
[order_total] => 4500.00
[sales_rep] => Mosby_Ted
)
)
I am trying to get an array that is set up more like this:
Array
(
[0] => stdClass Object
(
[sales_rep] => Doe_John
[total_sales] => 15800.00
)
[1] => stdClass Object
(
[sales_rep] => Mosby_Ted
[total_sales] => 4500.00
)
)
I want to combine all of the objects with the same "sales_rep" and get the sum of their associated "order_total", which you can see an example of in my desired array above. Any thoughts on how to accomplish this? I've been at it for hours now and have not been able to figure out a solution.
Thanks so much for the help!
try this
$tmp = array();
foreach($objs as $obj){ // where `$objs` is your objects
if(!in_array($obj->sales_rep,array_keys($tmp))){
$tmp[$obj->sales_rep] = (object)array(
'sales_rep' => $obj->sales_rep,
'total_sales' => $obj->order_total
);
}else{
$tmp[$obj->sales_rep]->total_sales += $obj->order_total;
}
}
print_r(array_values($tmp));
$obj0 = new StdClass();
$obj0->order_id = 1513;
$obj0->order_total = 12500.00;
$obj0->sales_rep = 'Doe_John';
$obj1 = new StdClass();
$obj1->order_id = 1046;
$obj1->order_total = 3300.00;
$obj1->sales_rep = 'Doe_John';
$obj2 = new StdClass();
$obj2->order_id = 337;
$obj2->order_total = 4500.00;
$obj2->sales_rep = 'Mosby_Ted';
$array = array(
$obj0,
$obj1,
$obj2,
);
$newArray = array();
foreach ($array as $item) {
if (array_key_exists($item->sales_rep, $newArray)) {
$newObj = $newArray[$item->sales_rep];
$newObj->order_total += $item->order_total;
} else {
$newObj = new StdClass();
$newObj->sales_rep = $item->sales_rep;
$newObj->order_total = $item->order_total;
$newArray[$newObj->sales_rep] = $newObj;
}
}
print_r(array_values($newArray));

Nested SimpleXML Attributes To Associative Array

I am integrating a payment gateway into a website and their API is returning an xml object where the values I require are nested.
SimpleXMLElement Object
(
[form] => SimpleXMLElement Object
(
[input] => Array
(
[0] => SimpleXMLElement Object
(
[#attributes] => Array
(
[type] => hidden
[name] => SessionStored
[value] => True
)
)
[1] => SimpleXMLElement Object
(
[#attributes] => Array
(
[type] => hidden
[name] => SessionStoredError
[value] =>
)
)
[2] => SimpleXMLElement Object
(
[#attributes] => Array
(
[type] => hidden
[name] => SST
[value] => e19e8abe-a2d6-4ce7
)
)
)
)
)
Using php how can I get the nested attributes into an associative array like the following format?
$array['SessionStored'] = 'True'
$array['SessionStoredError'] = ''
$array['SST'] = 'e19e8abe-a2d6-4ce7'
Its a bit messy but after reading other articles online I have put together the following which throws a 'Fatal error: Call to a member function attributes()'
$xmlData = simplexml_load_string($result);
$aXml = json_decode( json_encode($xmlData) , 1);
$testArray = $aXml['form']['input'];
for($i = 0; $i < count($testArray); $i++)
{
foreach($testArray[$i]->attributes() as $a => $b) {
echo $a,'="',$b,"\"\n";
}
}
Do not try to convert the XML.
Converting XML to JSON means loosing information. Generic conversion does not use the semantic structure. You don't have "nested attributes" just some input element nodes with attribute nodes.
Read it and generate the array from the data.
$result = [];
$element = new SimpleXMLElement($xml);
foreach ($element->form->input as $input) {
$result[(string)$input['name']] = (string)$input['value'];
}
var_dump($result);
Output:
array(3) {
["SessionStored"]=>
string(4) "True"
["SessionStoredError"]=>
string(0) ""
["SST"]=>
string(18) "e19e8abe-a2d6-4ce7"
}
This is easy with DOM, too:
$document = new DOMDocument();
$document->loadXml($xml);
$xpath = new DOMXpath($document);
$result = [];
foreach ($xpath->evaluate('//form/input') as $input) {
$result[$input->getAttribute('name')] = $input->getAttribute('value');
}
var_dump($result);

grabbing only certain array inside array

Basically, I'm receiving an array() from the Yahoo Messenger API in PHP and am in the process of developing an notification system, It returns an array with both the IM received from an chat and my contacts.
Array (
[0] => Array
(
[message] => Array
(
[status] => 1
[sequence] => 0
[sender] => SenderCurtis
[receiver] => receiverCurtis
[msg] => #1
[timeStamp] => 1374187598
[hash] => y2qlDf8uTq8tXzgzrsSMyjQB+W2uDg==
[msgContext] => y2qlDf8uTq8tXzgzrsSMyjQB+W2uDg==
)
)
[1] => Array
(
[buddyInfo] => Array
(
[sequence] => 1
[contact] => Array
(
[0] => Array
(
[sender] => SenderCurtis
[presenceState] => 0
[avatarUser] => 0
[avatarPreference] => 0
[clientCapabilities] => 8915971
[clientUserGUID] => MI7STHUYOAMCGE5TNTY7CJPFWM
)
)
)
)
[2] => Array
(
[message] => Array
(
[status] => 1
[sequence] => 2
[sender] => SenderCurtis
[receiver] => receiverCurtis
[msg] => #2
[timeStamp] => 1374187601
[hash] => 3+2s9sIvjPRdvneQsMgVNCKBTFgKwQ==
[msgContext] => 3+2s9sIvjPRdvneQsMgVNCKBTFgKwQ==
)
)
[3] => Array
(
[buddyInfo] => Array
(
[sequence] => 3
[contact] => Array
(
[0] => Array
(
[sender] => myContactUser1#yahoo.com
[presenceState] => 0
[avatarUser] => 0
[avatarPreference] => 0
[clientCapabilities] => 8915971
[clientUserGUID] => UQU3WV7ZOZ2OTGLJQUE2QJU4ZU
)
)
)
)
)
How can I grab just the message array() and iterate through it? such as "Message 1", "Message2" etc...
If you're trying to filter the array values for the key 'message', you could do something like this in PHP:
$messages = array();
foreach ($response as $key => $data) {
if (array_key_exists('message', $data)) {
$msgArray = $data['message'];
$messages[] = $msgArray;
}
}
In the above sample, I'm storing the messages in their own array. But you could process the data right inside the for-loop too, if you want that.
I think that array_map() is the function you are looking for here. The array_map function allows you to execute a callback on each element of an existing array and assemble a new array consisting only of the values returned by the callback.
What you would want to do is something like this :
$data = // lets assume this is the data you received
$messages_data = array_map( "extract_message", $data );
function extract_message( $data_item ){
if ( array_key_exists( 'message', $data_item ) ){
return $data_item[ 'message' ];
}
}
Now your $message_data array will contain only the message arrays from the original array.
foreach ($var[0] as $key => $value)
{
do things with each message
}
where $var is substituted for your actual variable name
Just filter your array using array_filter.
$messages = array_filter($data, function($a){ return isset($a["message"]); });
Then use array_map to get rid of the unwanted intermediate array.
$messages = array_map(function($a){ return $a["message"]; }, $message);
then you can iterate over it with a foreach or whatever.
Because I like SPL iterators here another solution. Works with PHP >= 5.1.0.
class MessageIterator extends FilterIterator
{
public function accept()
{
return array_key_exists('message', $this->getInnerIterator()->current());
}
public function current()
{
$current = parent::current();
return $current['message'];
}
}
$iterator = new MessageIterator(new ArrayIterator($array));
foreach ($iterator as $message) {
print_r($message);
}

Categories