Please read the bolded line below before you comment that this may be a duplicate. This has nothing to do with SimpleXML.
Let me start off by showing how the XML should be laid out. Please ignore the namespaces:
<hot:SearchHotels>
<hot:request>
<hot1:Destination>?</hot1:Destination>
<hot1:HotelCityName>?</hot1:HotelCityName>
<hot1:HotelLocationName>?</hot1:HotelLocationName>
<hot1:HotelName>?</hot1:HotelName>
<hot1:CheckIn>?</hot1:CheckIn>
<hot1:CheckOut>?</hot1:CheckOut>
<hot1:RoomsInformation>
<!--Zero or more repetitions:-->
<hot1:RoomInfo>
<hot1:AdultNum>?</hot1:AdultNum>
<hot1:ChildNum>?</hot1:ChildNum>
<!--Optional:-->
<hot1:ChildAges>
<!--Zero or more repetitions:-->
<hot1:ChildAge age="?"/>
</hot1:ChildAges>
</hot1:RoomInfo>
</hot1:RoomsInformation>
<hot1:MaxPrice>?</hot1:MaxPrice>
<hot1:StarLevel>?</hot1:StarLevel>
<hot1:AvailableOnly>?</hot1:AvailableOnly>
<hot1:PropertyType>?</hot1:PropertyType>
<hot1:ExactDestination>?</hot1:ExactDestination>
</hot:request>
</hot:SearchHotels>
Notice under hot1:RoomsInformation there is RoomInfo. I'm supposed to be able to send multiple RoomInfo nodes. But I'm using a PHP class to convert an array to this object to be submitted via SOAP.
Here's my array before it gets converted to an object:
$param = array(
"Destination" => $destcode,
"HotelCityName" => $city,
"HotelLocationName" => "",
"HotelName" => "",
"CheckIn" => date("Y-m-d", strtotime($checkin)),
"CheckOut" => date("Y-m-d", strtotime($checkout)),
"RoomsInformation" => array (
"RoomInfo" => array(
"AdultNum" => 2,
"ChildNum" => 1,
"ChildAges" => array(
"ChildAge" => array(
"age"=>11
)
)
),
"RoomInfo" => array(
"AdultNum" => 1,
"ChildNum" => 0,
"ChildAges" => array(
"ChildAge" => array(
"age"=>0
)
)
)
),
"MaxPrice" => 0,
"StarLevel" => 0,
"AvailableOnly" => "false",
"PropertyType" => "NotSet",
"ExactDestination" => "false"
);
$param = arrayToObject($param) ;
$obj = new stdClass();
$obj->request=$param;
$result = $test->SearchHotels($obj) ;
The problem is that after converting to an Object, there is only 1 RoomInfo and its the last one. My thought is because the RoomsInformation array has 2 identical KEY names. So how can I make this work?
For your information, here is the SOAP class I use and the arrayToObject function:
http://pastebin.com/SBUN0FAF
The problem is, your array is invalid as you suspected because of the duplicate keys. One way to solve the issue is to wrap each "RoomInfo" in its own array like so:
$param = array(
"Destination" => $destcode,
"HotelCityName" => $city,
"HotelLocationName" => "",
"HotelName" => "",
"CheckIn" => date("Y-m-d", strtotime($checkin)),
"CheckOut" => date("Y-m-d", strtotime($checkout)),
"RoomsInformation" => array (
array(
"RoomInfo" => array(
"AdultNum" => 2,
"ChildNum" => 1,
"ChildAges" => array(
"ChildAge" => array(
"age"=>11
)
)
),
),
array(
"RoomInfo" => array(
"AdultNum" => 1,
"ChildNum" => 0,
"ChildAges" => array(
"ChildAge" => array(
"age"=>0
)
)
)
)
),
"MaxPrice" => 0,
"StarLevel" => 0,
"AvailableOnly" => "false",
"PropertyType" => "NotSet",
"ExactDestination" => "false"
);
And you can generate the XML like this:
// create simpleXML object
$xml = new SimpleXMLElement("<?xml version=\"1.0\"?><SearchHotels></SearchHotels>");
$node = $xml->addChild('request');
// function call to convert array to xml
array_to_xml($param, $node);
// display XML to screen
echo $xml->asXML();
die();
// function to convert an array to XML using SimpleXML
function array_to_xml($array, &$xml) {
foreach($array as $key => $value) {
if(is_array($value)) {
if(!is_numeric($key)){
$subnode = $xml->addChild("$key");
array_to_xml($value, $subnode);
} else {
array_to_xml($value, $xml);
}
} else {
$xml->addChild("$key","$value");
}
}
}
I attribute the array_to_xml function to the wonderful author here: https://stackoverflow.com/a/5965940/2200766
It looks as though you should have your array like this, instead;
$param = array(
"Destination" => $destcode,
"HotelCityName" => $city,
"HotelLocationName" => "",
"HotelName" => "",
"CheckIn" => date("Y-m-d", strtotime($checkin)),
"CheckOut" => date("Y-m-d", strtotime($checkout)),
"RoomsInformation" => array (
"RoomInfo" => array(
array(
"AdultNum" => 2,
"ChildNum" => 1,
"ChildAges" => array(
"ChildAge" => array(
"age"=>11
)
)
),
array(
"AdultNum" => 1,
"ChildNum" => 0,
"ChildAges" => array(
"ChildAge" => array(
"age"=>0
)
)
)
)
),
"MaxPrice" => 0,
"StarLevel" => 0,
"AvailableOnly" => "false",
"PropertyType" => "NotSet",
"ExactDestination" => "false"
);
This will preserve the two RoomInfo array elements.
simply use this function, where $data is multideminsional array
function array_to_xml( $data ) {
$xml_data = new SimpleXMLElement('<?xml version="1.0"?><data></data>');
foreach( $data as $key => $value ) {
$node = $xml_data->addChild('row_' . $key);
foreach( $value as $keyx => $valuex ) {
$node->addChild($keyx,$valuex);
}
}
return $xml_data->asXML();
}
Related
I have this PHP array:
$statuses = array(
'delivery-ongoing' => array("status" => "at-10", "traffic" => "FCL", "type" => "export"),
'delivered' => array("status" => "at-13", "traffic" => "FCL", "type" => "export"),
'delivery-ongoing' => array("status" => "00--00", "traffic" => "FCL", "type" => "import"),
'return-to-ongoing' => array("status" => "to-04", "traffic" => "FCL", "type" => "import"),
'delivered' => array("status" => "at-13", "traffic" => "FCL", "type" => "import")
);
I have to select status by key "delivery-ongoing" where type = "import"
I can play with the array structure since is a constant within my class.
I tried
$statuses['delivery-ongoing']['status']
How do I get the right status for type = "import"
Is there a sort of loop I have to do or there is another way to do this?
You can use array_filter
$filtered = array_filter($statuses, function($value, $key) {
return ($key == 'delivery-ongoing' && $value['type'] == 'import');
}, ARRAY_FILTER_USE_BOTH);
print_r($filtered);
Also, as it has been suggested in the comments, you can re-name your keys, maybe by appending an ID after the status.
Eq:
'delivery-ongoing-101' => array("status" => "at-10", "traffic" => "FCL", "type" => "export"),
There are several problems with this array:
1- There's an error in a parenthesis that is closed too early at this line:
'return-to-ongoing' => array("status" => "to-04", "traffic" => "FCL"), "type" => "import",
2- If you define the same key two times on the same array, you won't be able to access the first element that was defined with this key. If you use a debugger, you will see that only 3 elements are available in your array, cause there are more than one that share the same key and only the last one is saved.
But to get the value that you are looking for, you can use this loop:
foreach ($statuses as $key => $value) {
if($key == 'delivery-ongoing' && $value['type'] == 'import'){
$result = $value['status'];
break;
}
}
The status for the type import is available at $result after the loop ends.
Your $statuses must have the following structure:
$statuses = array(
'delivery-ongoing' => array(
array("status" => "at-10", "traffic" => "FCL", "type" => "export"),
array("status" => "00--00", "traffic" => "FCL", "type" => "import")
),
'delivered' => array(
array("status" => "at-13", "traffic" => "FCL", "type" => "export"),
array("status" => "at-13", "traffic" => "FCL", "type" => "import")
),
'return-to-ongoing' => array(array("status" => "to-04", "traffic" => "FCL", "type" => "import")),
);
Now, you can do what you want to do by doing:
function filter_by_value ($array, $index, $value){
if(is_array($array) && count($array)>0)
{
foreach(array_keys($array) as $key){
$temp[$key] = $array[$key][$index];
if ($temp[$key] == $value){
$newarray[$key] = $array[$key];
}
}
}
return $newarray;
}
$imported = filter_by_value($statuses['delivery-ongoing'], 'type', 'import');
print_r($imported);
I'm trying to extract data from a multidimensional array and then putting into one of my own so that I can load it into my database.
Source:
array( "ListOrdersResult" =>
array ( "Orders" =>
array( "Order" =>
array( [0] => {
"Title" => $productTitle,
"customer_name" => $customerName,
"customer_id" => $customerId,
"random_info" => $randomInfo
},
[1] => {
"Title" => $productTitle,
"customer_name" => $customerName,
"customer_id" => $customerId,
"random_info" => $randomInfo
}
)
)
)
To do this, I'm cycling through it like this - I have no issues with extracting data.
My code:
$count = count($listOrderArray['ListOrdersResult']['Orders']['Order']);
//Cycle through each Order to extract the data I want
for($i = 0; $count > $i; $i++) {
$baseArray = $listOrderArray['ListOrdersResult']['Orders']['Order'][$i];
foreach($baseArray as $key => $value) {
if($key == "Title" || $key == "customer_id") {
//ADD TO multidimensional array
}
}
}
How I'm trying to structure it.
array( [0] => {
array(
"Title" => $title,
"customer_id" => $customer_id
},
[1] => {
"Title" => $nextTitle,
"customer_id" => $next_customer_id
}
);
The ultimate goal is to make it easier to load the information into the database by gathering the data by record and then loading it to the database rather than loading by creating an new record and then coming back and modifying that record. To me that seems like it would take more resources and has a higher chance of inconsistent data, but I'm new so I could be wrong.
Any help would be greatly appreciated.
You only have to unset keys you don't want:
$result = array_map(function ($i) {
unset($i['customer_name'], $i['random_info']);
return $i;
}, $listOrderArray['ListOrdersResult']['Orders']['Order']);
More about array_map
Or you also can select the keys you want:
$result = array_map(function ($i) {
return ['Title' => $i['Title'], 'customer_id' => $i['customer_id']];
}, $listOrderArray['ListOrdersResult']['Orders']['Order']);
About your code and question:
$count = count($listOrderArray['ListOrdersResult']['Orders']['Order']);
//Cycle through each Order to extract the data I want
for($i = 0; $count > $i; $i++) {
There's no reason to use a count and a for loop, use foreach.
array( [0] => {
array(
"Title" => $title,
"customer_id" => $customer_id
},
[1] => {
"Title" => $nextTitle,
"customer_id" => $next_customer_id
}
);
doesn't make sense, what are these curly brackets? You should write it like this if you want to be understood:
array(
[0] => array(
"Title" => "fakeTitle0",
"customer_id" => "fakeCustomerId0"
),
[1] => array(
"Title" => "fakeTitle1",
"customer_id" => "fakeCustomerId1"
)
);
You have this initial variable.
$listOrderArray = array(
"ListOrdersResult" => array(
"Orders" => array(
"Order" => array(
0 => array(
"Title" => "productTitle",
"customer_name" => "customerName",
"customer_id" => "customerId",
"random_info" => "randomInfo",
),
1 => array(
"Title" => "productTitle",
"customer_name" => "customerName",
"customer_id" => "customerId",
"random_info" => "randomInfo",
),
)
)
)
);
The only thing you should do is to remove the inner array from the three outer arrays.
Here is the solution:
$orders = $listOrderArray['ListOrdersResult']['Orders']['Order'];
I want to compare a value of data to a list of element which I had retrieved from php array(decoded json).
First,
This is the first array:
Array1
(
[0] => Array
(
[member_id] => 3
[member_card_num] => 2013011192330791
[member_barcode] => 2300067628912
)
[1] => Array
(
[member_id] => 4
[member_card_num] => 2328482492740000
[member_barcode] => 3545637000
)
[2] => Array
(
[member_id] => 2
[member_card_num] => 40001974318
[member_barcode] => 486126
)
[3] => Array
(
[member_id] => 1
[member_card_num] => 91001310000057698
[member_barcode] => 000057698
)
)
This is the second Array:
Array2
(
[0] => Array
(
[member_id] => 2
[member_card_num] => 40001974318
[member_barcode] => 486126
)
)
Second,
I had retrieved the (member_barcode) which I required.
Here is the code:
For Array1:
foreach ($decode1 as $d){
$merchant_barcode = $d ['member_barcode'];
echo $merchant_barcode;
}
For Array2:
foreach ($decode2 as $d2){
$user_barcode = $d2 ['member_barcode'];
echo $user_barcode;
}
Then,
I get this output():
For Array1(merchant_barcode):
2300067628912
3545637000
486126
000057698
For Array2(user_barcode):
486126
The question is, I would to check and compare whether the user_barcode in Array2(486126) is exist/match to one of the merchant_barcode in Array1.
This is my code,
but it only compare the user_barcode in Array2 to the last element(000057698) in Array1,
I want it to loop through each n check one by one. How can I do that?
public function actionCompareBarcode($user_barcode, $merchant_barcode){
if(($user_barcode) == ($merchant_barcode)){
echo "barcode exist. ";
}
else{
echo "barcode not exist";
}
}
In this case, the output I get is "barcode not exist", but it should be "barcode exist".
Anyone can help? Appreciate that. Im kinda new to php.
You could use a nested loop like:
foreach ($decode2 as $d2)
{
$user_barcode = $d2 ['member_barcode'];
foreach ($decode1 as $d)
{
$merchant_barcode = $d ['member_barcode'];
if ($merchant_barcode == $user_barcode)
{
echo "Match found!";
}
else
{
echo "No match found!";
}
}
}
<?
$a = array(
array(
'member_id' => 3,
'member_card_num' => '2013011192330791',
'member_barcode' => '2300067628912',
),
array(
'member_id' => 4,
'member_card_num' => '2328482492740000',
'member_barcode' => '3545637000',
),
array(
'member_id' => 2,
'member_card_num' => '40001974318',
'member_barcode' => '486126',
),
array(
'member_id' => 1,
'member_card_num' => '91001310000057698',
'member_barcode' => '000057698',
)
);
$b = array(
array(
'member_id' => 2,
'member_card_num' => '40001974318',
'member_barcode' => '486126',
)
);
array_walk($a, function($item) use($b) {
echo ($b['0']['member_barcode'] == $item['member_barcode'] ? "found" : NULL);
});
?>
I'd use array_uintersect() to calculate if those multidimensional arrays have a common element:
<?php
$a = array(
array(
'member_id' => '3',
'member_card_num' => '2013011192330791',
'member_barcode' => '2300067628912',
),
array(
'member_id' => '2',
'member_card_num' => '40001974318',
'member_barcode' => '486126',
)
);
$b = array(
array(
'member_id' => '2',
'member_card_num' => '40001974318',
'member_barcode' => '486126',
)
);
$match = array_uintersect($a, $b, function($valueA, $valueB) {
return strcasecmp($valueA['member_barcode'], $valueB['member_barcode']);
});
print_r($match);
Try calling that method as you are looping through Array1 and comparing the user_barcode to every value
You can compare two array this way too:
$per_arr = array();
$permissions = array()
foreach ($per_arr as $key => $perms) {
if(isset($permissions[$key]['name'])){
echo $per_arr[$key]['name']; //matched data
}else{
echo $per_arr[$key]['name']; //not matched data
}
}
I need to create a similar array to this:
$need = Array(
"smsSend" => Array(
"account" => Array(
"user" => 123,
"password" => "xxxxxx",
"profile" => 123456
)
),
"smsConfig" => Array
(
"region" => Array
(
"locale" => "es_ES",
"timezone" => "America/Bogota"
),
"send" => Array
(
"from" => "9:00:00",
"to" => "21:00:00"
),
"sms" => Array
(
"channel" => "SMS",
"from" => "LINIO",
)
),
"templateConfig" => Array
(
"template" => Array
(
"postpago" => 1111,
"prepago" => 0010,
"notificar" => 1112
)
),
"fieldsConfig" => Array
(
"fields" => Array
(
"nombre" => "firstname",
"carrier" => "nome_transportadora",
"track" => "track",
"cantidad" => "total_depois_de_impostos"
)
),
"serverConfig" => Array
(
"test" => "http://miportal",
"prod" => "",
"mode" => "test",
"adapter" => "curl",
"type" => "post",
"telephone" => "12345"
),
"fields" => Array
(
"sms" => Array
(
"address" => "mobile_phone"
),
"email" => Array
(
"address" => "email_cliente"
)
)
);
From this arrangement to receive from $_POST:
$post = Array(
"smsSend" => Array(
"account" => Array(
"user:123",
"password:xxxxxx",
"profile:123456"
)
),
"smsConfig" => Array
(
"region" => Array
(
"locale:es_ES",
"timezone:America/Bogota"
),
"send" => Array
(
"from:9:00:00",
"to:21:00:00"
),
"sms" => Array
(
"channel:SMS",
"from:LINIO",
)
),
"templateConfig" => Array
(
"template" => Array
(
"postpago:1111",
"prepago:0010",
"notificar:1112"
)
),
"fieldsConfig" => Array
(
"fields" => Array
(
"nombre:firstname",
"carrier:nome_transportadora",
"track:track",
"cantidad:total_depois_de_impostos"
)
),
"serverConfig" => Array
(
"test:http://miportal",
"prod:",
"mode:test",
"adapter:curl",
"type:post",
"telephone:12345"
),
"fields" => Array
(
"sms" => Array
(
"address:mobile_phone"
),
"email" => Array
(
"address:email_cliente"
)
)
);
The problem is the cycle to assemble items of the parent, I use tree function to create levels:
function createLevel1($array_data) {
$array_push = array();
foreach ($array_data as $key_l1 => $elem_l1) {
array_push($array_push[$key_l1], "");
createLevel2($elem_l1, $array_push, $key_l1);
// print_r($resl1);
}
return $array_push;
}
function createLevel2($elemento_array, $push_array, $parent_key) {
foreach ($elemento_array as $key_l2 => $elem_l2) {
if (is_array($elem_l2)) {
$push_array[$parent_key][$key_l2] = "";
createLevel3($elem_l2, $push_array, $parent_key, $key_l2);
} else {
$items = explode("::", $elem_l2);
$push_array[$parent_key][$items[0]] = $items[1];
}
}
return $push_array;
}
function createLevel3($elemento_array, $push_array, $parent_key, $parentl2_key) {
$push_array[$parent_key][$parentl2_key] = "";
foreach ($elemento_array as $key_l3 => $elem_l3) {
if (is_array($elem_l3)) {
createLevel3($elem_l3, $push_array, $parent12_key, $key_l3);
} else {
$items = explode("::", $elem_l3);
$push_array[$parent_key][$parentl2_key][$items[0]] = $items[1];
}
}
return $push_array;
}
$parameter = $_POST['postData'];
#$info = createLevel1($parameter);
print_r($parameter);
The value of the parameter is array $post, the problem is when I print the result $info like this, the option is blank.:
Array
(
[smsSend] =>
[smsConfig] =>
[templateConfig] =>
[fieldsConfig] =>
[serverConfig] =>
[fields] => Array
(
[sms] =>
[email] =>
)
)
$need = array();
foreach ($post as $key => $value) {
if (is_array($value)) {
$need[$key] = $value;
foreach ($value as $key2 => $value2) {
if (is_array($value2)) {
foreach ($value2 as $key3 => $value3) {
if (is_array($value3)) {
} elseif (strpos($value3, ':') !== FALSE) {
$tmp3 = explode(':', $value3);
$need[$key][$key2][$tmp3[0]] = $tmp3[1];
unset($need[$key][$key2][$key3]);
}
}
} elseif (strpos($value2, ':') !== FALSE) {
$tmp2 = explode(':', $value2);
$need[$key][$tmp2[0]] = $tmp2[1];
unset($need[$key][$key2]);
}
}
}
}
I have wrote this code. I think it is working. But issue is there. when i use explode it divide http://miportal.com also. try another method like strstr. Try it with recursive function.
I've written the follow code to try and insert data into a table on the database. However it's just inserting letters. I'm not sure what I'm doing wrong.
$media_items = array(
array (
"media_name" => "Facebook",
"link_url" => "http://www.facebook.com/insightdezign",
"icon" => "facebook.png",
"size" => "48",
"order" => "0"
),
array (
"media_name" => "Twitter",
"link_url" => "http://www.twitter.com/insightdezign",
"icon" => "twitter.png",
"size" => "48",
"order" => "1"
)
);
foreach ($media_items as $media_item) {
if (is_array($media_item)){
foreach ($media_item as $item) {
$rows_affected = $wpdb->insert( $ffui_items, array( 'media_name' => $item['media_name'], 'link_url' => $item['link_url'], 'icon' => $item['icon'], 'size' => $item['size'], 'order' => $item['order'] ) );
}
}
}
Inside your nested foreach loop, you will be looping over strings, not arrays. As a result of type juggling, the indexes will be evaluated to 0. Since PHP also accepts $foo['bar'] syntax on strings, it will just return the first letter.
You can simply remove the nested foreach loop and do it as follows:
foreach ($media_items as $media_item)
{
if (is_array($media_item))
{
$rows_affected = $wpdb->insert( $ffui_items,
array(
'media_name' => $media_item['media_name'],
'link_url' => $media_item['link_url'],
'icon' => $media_item['icon'],
'size' => $media_item['size'],
'order' => $media_item['order']
) ;
}
}