PHP Reconstruct array Paypal TransactionSearch Function - php

I am making a call to Paypals API TransactionSearch and I am getting back a flat array of data. I am needing to reconstruct this array. Here is the structure that I get back from paypal:
array(36){
[
"L_TIMESTAMP0"
]=>string(28)"2012%2d09%2d18T22%3a10%3a13Z"[
"L_TIMESTAMP1"
]=>string(28)"2012%2d09%2d18T19%3a55%3a41Z"[
"L_TIMESTAMP2"
]=>string(28)"2012%2d09%2d18T19%3a55%3a41Z"[
"L_TIMEZONE0"
]=>string(3)"GMT"[
"L_TIMEZONE1"
]=>string(3)"GMT"[
"L_TIMEZONE2"
]=>string(3)"GMT"[
"L_TYPE0"
]=>string(7)"Payment"[
"L_TYPE1"
]=>string(7)"Payment"[
"L_TYPE2"
]=>string(7)"Payment"[
"L_EMAIL0"
]=>string(26)"XXXXX%40hotmail%2ecom"[
"L_EMAIL1"
]=>string(31)"XXXX%40lvcoxmail%2ecom"[
"L_EMAIL2"
]=>string(23)"XXXXt%2ecom"[
"L_TRANSACTIONID0"
]=>string(17)"13E586955G649992Y"[
"L_TRANSACTIONID1"
]=>string(17)"8LH96897T3119113R"[
"L_TRANSACTIONID2"
]=>string(17)"87U867057E085230E"[
"L_STATUS0"
]=>string(9)"Completed"[
"L_STATUS1"
]=>string(9)"Completed"[
"L_STATUS2"
]=>string(9)"Completed"[
"L_AMT0"
]=>string(7)"85%2e00"[
"L_AMT1"
]=>string(7)"85%2e00"[
"L_AMT2"
]=>string(7)"85%2e00"[
"L_CURRENCYCODE0"
]=>string(3)"USD"[
"L_CURRENCYCODE1"
]=>string(3)"USD"[
"L_CURRENCYCODE2"
]=>string(3)"USD"[
"L_FEEAMT0"
]=>string(9)"%2d2%2e17"[
"L_FEEAMT1"
]=>string(9)"%2d2%2e17"[
"L_FEEAMT2"
]=>string(9)"%2d2%2e17"[
"L_NETAMT0"
]=>string(7)"82%2e83"[
"L_NETAMT1"
]=>string(7)"82%2e83"[
"L_NETAMT2"
]=>string(7)"82%2e83"[
"TIMESTAMP"
]=>string(28)"2012%2d11%2d08T14%3a24%3a30Z"[
"CORRELATIONID"
]=>string(13)"52c22d68648cd"[
"ACK"
]=>string(7)"Success"[
"VERSION"
]=>string(6)"51%2e0"[
"BUILD"
]=>string(7)"4137385"
}
I need to reset the array to just the following:
["L_STATUSn"]=>string(9)"Completed"
["L_TRANSACTIONIDn"]=>string(17)"8LH96897T3119113R"
with 'n' being the number, being the array key number that paypal returns.
Here is the code I am using, and it is borked.
$i = 0;
$c = 0;
foreach ($comparison AS $aKey => $v) {
$findme1 = 'L_TIMESTAMP'.$i++;
$findme2 = 'L_STATUS'.$c++;
$txid = $myarray[$findme1];
$status = $myarray[$findme2];
$TXid = array_search('$findme1', $aKey);
$Status = array_search('$findme2', $aKey);
$TxID[] = array('Status' => $aStatus, 'TransactionID' => $aTransactionID);
}
appreciate abetter way to reconstruct this array, the method I am trying to use doesnt appear to be too efficient.

Somewhat late, but maybe others have this request too. So here goes:
function process_response($str)
{
$data = array();
$x = explode("&", $str);
foreach($x as $val)
{
$y = explode("=", $val);
preg_match_all('/^([^\d]+)(\d+)/', $y[0], $match);
if (isset($match[1][0]))
{
$text = $match[1][0];
$num = $match[2][0];
$data[$num][$text] = urldecode($y[1]);
}
else
{
$text = $y[0];
// $data[$text] = urldecode($y[1]);
}
}
return $data;
}
Just feed the result from your curl call into this and take the result as a formatted array.
Note the commented out line, there are some fields that are global, such as version, if you want these, uncomment, but then you may have to adjust some formatting code down stream.
if you want to feed this into PHPExcel object, you could do so like so:
$index = 1;
foreach($data as $row)
{
$objPHPExcel->setActiveSheetIndex(0)
->setCellValue('A'.$index, $row['L_TIMESTAMP'])
->setCellValue('B'.$index, $row['L_TIMEZONE'])
->setCellValue('C'.$index, $row['L_TYPE'])
->setCellValue('D'.$index, $row['L_EMAIL'])
->setCellValue('E'.$index, $row['L_NAME'])
->setCellValue('F'.$index, $row['L_TRANSACTIONID'])
->setCellValue('G'.$index, $row['L_STATUS'])
->setCellValue('H'.$index, $row['L_AMT'])
->setCellValue('I'.$index, $row['L_CURRENCYCODE'])
->setCellValue('J'.$index, $row['L_FEEAMT'])
->setCellValue('K'.$index, $row['L_NETAMT']);
$index++;
}

Related

Show only a specific part of html response in php

I am trying to get tracking information from amazon using provided url
https://www.amazon.co.uk/progress-tracker/package/ref=pe_3187911_189395841_TE_typ?_encoding=UTF8&from=gp&itemId=&orderId=203-2171364-3066749&packageIndex=0&shipmentId=23796758607302
I am getting response using file_get_contents() function in php,
what I want is to show only that part of the response which contains the tracking information as an output of my php script and eliminate/hide all the unnecessary content from file_get_contents() response.
One way to do what you're looking for is use DomDocument to filter out the json data in the source ($file) and then use a recursive function to get the elements you need.
You can set the elements you need using an array, $filter. In this example we've taken a sample of some of the available data, i.e. :
$filter = [
'orderId', 'shortStatus', 'promiseMessage',
'lastTransitionPercentComplete', 'lastReachedMilestone', 'shipmentId',
];
The code
<?php
$filename = 'https://www.amazon.co.uk/progress-tracker/package/ref=pe_3187911_189395841_TE_typ?_encoding=UTF8&from=gp&itemId=&orderId=203-2171364-3066749&packageIndex=0&shipmentId=23796758607302';
$file = file_get_contents($filename);
$trackingData = []; // store for order tracking data
$html = new DOMDocument();
#$html->loadHTML($file);
foreach ($html->getElementsByTagName('script') as $a) {
$data = $a->textContent;
if (stripos($data, 'shortStatus') !== false) {
$trackingData = json_decode($data, true);
break;
}
}
// set the items we need
$filter = [
'orderId', 'shortStatus', 'promiseMessage',
'lastTransitionPercentComplete', 'lastReachedMilestone', 'shipmentId',
];
// invoke recursive function to pick up the data items specified in $filter
$result = getTrackingData($filter, $trackingData);
echo '<pre>';
print_r($result);
echo '</pre>';
function getTrackingData(array $filter, array $data, array &$result = []) {
foreach($data as $key => $value) {
if(is_array($value)) {
getTrackingData($filter, $value, $result);
} else {
foreach($filter as $item) {
if($item === $key) {
$result[$key] = $value;
}
}
}
}
return $result;
}
Output:
Array
(
[orderId] => 203-2171364-3066749
[shortStatus] => IN_TRANSIT
[promiseMessage] => Arriving tomorrow by 9 PM
[lastTransitionPercentComplete] => 92
[lastReachedMilestone] => SHIPPED
[shipmentId] => 23796758607302
)
Try this
<?php
$filename = 'https://www.amazon.co.uk/progress-tracker/package/ref=pe_3187911_189395841_TE_typ?_encoding=UTF8&from=gp&itemId=&orderId=203-2171364-3066749&packageIndex=0&shipmentId=23796758607302';
$file = file_get_contents($filename);
$html = new DOMDocument();
#$html->loadHTML($file);
foreach($html->getElementsByTagName('span') as $a) {
$property=$a->getAttribute('id');
if (strpos($property , "primaryStatus"))
print_r($property);
}
?>
It should show "Arriving tomorrow by 9 PM" status.

A better way to flatten an array in PHP

I require the array keys to be maintained, with a number appended to the key to make it unique when flattening an array.
Example input:
$array = array(
array("name"=>"bob", "age"=>32, "third_param"=>"something"),
array("name"=>"ted", "age"=>57, "third_param"=>"something else"),
array("name"=>"ned", "age"=>103, "third_param"=>"another something"),
);
Required output:
$array = array(
"name-1"=>"bob",
"age-1"=>32,
"third_param-1"=>"something",
"name-2"=>"ted",
"age-2"=>57,
"third_param-2"=>"something else",
"name-3"=>"ned",
"age-3"=>103,
"third_param-3"=>"another something"
);
I was able to figure out how to do it, but my solution is slow and messy. There has got to be a better way.
Here's my current function:
function flatten_array($array, $flat = array()) {
foreach($array as $k=>$v){
$k = strval($k);
if(!is_array($v)){
$i = 0;
while(true){
$i++;
$key = $k."-".strval($i);
if(!isset($flat[$key])) break;
}
$flat[$key] = $v;
}else{
$flat = flatten_array($v, $flat);
}
}
return $flat;
}
Here's an example usage: http://3v4l.org/6QVj0/
(Hit the execute button, and then have a look at the "Performance" tab.
This takes a long time and has timed-out on me when testing it on real data, however it does produce the result I need. What can I do to this to make it quicker and not take up so much memory?
$ar = array();
foreach ($array as $i => $items) {
foreach ($items as $key => $value) {
$ar[$key.'-'.($i+1)] = $value;
}
}

What is the best way to search through an array to return the key of a sub value

I'm trying to filter an array (derived from a json object), so as to return the array key based on the value. I'm not sure if array search $key = array_search($value, $array); is the best way to do this (I can't make it work), and I think there must be a better way.
So far I've got this, but it isn't working. Grateful for any help!
public function getBedroomData(array $data,$num_beds = null,$type) {
$data = (array) $data;
if($num_beds > 0) {
$searchstring = "avg_".$num_beds."bed_property_".$type."_monthly";
} else {
$searchstring = "avg_property_".$type."_monthly";
}
$avg_string = array_search($data, $searchstring);
return $avg_string;
}
The array consists of average property prices taken from the nestoria api as follows:
http://api.nestoria.co.uk/api?country=uk&pretty=1&action=metadata&place_name=Clapham&price_type=fixed&encoding=json
This returns a long json object. My problem is that the data isn't consistent - and I'm looking for the quickest (run time) way to do the following:
$data['response']['metadata']['0'] //= data to return, [0] unknown
$data['response']['metadata']['0']['metadata_name'] = "avg_1bed_property_rent_monthly" //= string I know!
$data['response']['metadata']['1'] //= data to return, [1] unknown
$data['response']['metadata']['1']['metadata_name'] = "avg_1bed_property_buy_monthly" //= string I know!
$data['response']['metadata']['2'] = //= data to return, [2] unknown
$data['response']['metadata']['2']['metadata_name'] = "avg_2bed_property_buy_monthly" //= string I know!
.....
.....
.....
$data['response']['metadata']['10'] = avg_property_rent_monthly
$data['response']['metadata']['11'] = avg_property_buy_monthly
$data['response']['metadata'][most_recent_month] = the month reference for getting the data from each metadata list..
It isn't possible to filter the initial search query by number of bedrooms as far as I can work out. So, I've just been array slicing the output to get the information I've needed if bedrooms are selected, but as the data isn't consistent this often fails.
To search inside that particular json response from nestoria, a simple foreach loop can be used. First off, of course call the json data that you need. Then, extract the whole data, the the next step if pretty straightforward. Consider this example:
$url = 'http://api.nestoria.co.uk/api?country=uk&pretty=1&action=metadata&place_name=Clapham&price_type=fixed&encoding=json';
$contents = file_get_contents($url);
$data = json_decode($contents, true);
$metadata = $data['response']['metadata'];
// dummy values
$num_beds = 1; // null or 0 or greater than 0
$type = 'buy'; // buy or rent
function getBedroomData($metadata, $num_beds = null, $type) {
$data = array();
$searchstring = (!$num_beds) ? "avg_property_".$type."_monthly" : "avg_".$num_beds."bed_property_".$type."_monthly";
$data['metadata_name'] = $searchstring;
$data['data'] = null;
foreach($metadata as $key => $value) {
if($value['metadata_name'] == $searchstring) {
$raw_data = $value['data']; // main data
// average price and data points
$avg_price = 0;
$data_points = 0;
foreach($raw_data as $index => $element) {
$avg_price += $element['avg_price'];
$data_points += $element['datapoints'];
}
$data_count = count($raw_data);
$price_average = $avg_price / $data_count;
$data_points_average = $data_points / $data_count;
$data['data'][] = array(
'average_price' => $price_average,
'average_datapoints' => $data_points_average,
'data' => $raw_data,
);
}
}
return $data;
}
$final = getBedroomData($metadata, $num_beds, $type);
print_r($final);

How to reference cells with specific condition in php multidimensional array

I got an array like this:
$array[0][name] = "Axel";
$array[0][car] = "Pratzner";
$array[0][color] = "black";
$array[1][name] = "John";
$array[1][car] = "BMW";
$array[1][color] = "black";
$array[2][name] = "Peggy";
$array[2][car] = "VW";
$array[2][color] = "white";
I would like to do something like "get all names WHERE car = bmw AND color = white"
Could anyone give advice on how the PHP spell would look like?
function getWhiteBMWs($array) {
$result = array();
foreach ($array as $entry) {
if ($entry['car'] == 'bmw' && $entry['color'] == 'white')
$result[] = $entry;
}
return $result;
}
Edited: This is a more general solution:
// Filter an array using the given filter array
function multiFilter($array, $filters) {
$result = $array;
// Removes entries that don't pass the filter
$fn = function($entry, $index, $filter) {
$key = $filter['key'];
$value = $filter['value'];
$result = &$filter['array'];
if ($entry[$key] != $value)
unset($result[$index]);
};
foreach ($filters as $key => $value) {
// Pack the filter data to be passed into array_walk
$filter = array('key' => $key, 'value' => $value, 'array' => &$result);
// For every entry, run the function $fn and pass in the filter data
array_walk($result, $fn, $filter);
}
return array_values($result);
}
// Build a filter array - an entry passes this filter if every
// key in this array corresponds to the same value in the entry.
$filter = array('car' => 'BMW', 'color' => 'white');
// multiFilter searches $array, returning a result array that contains
// only the entries that pass the filter. In this case, only entries
// where $entry['car'] = 'BMW' AND $entry['color'] = 'white' will be
// returned.
$whiteBMWs = multiFilter($array, $filter);
Doing this in code is more or less emulating what a RDBMS is perfect for. Something like this would work:
function getNamesByCarAndColor($array,$color,$car) {
$matches = array();
foreach ($array as $entry) {
if($entry["color"]== $color && $entry["car"]==$car)
matches[] = $entry["name"];
}
return $matches;
}
This code would work well for smaller arrays, but as they got larger and larger it would be obvious that this isn't a great solution and an indexed solution would be much cleaner.

PHP Can't get the right format for array

I got stuck somehow on the following problem:
What I want to achieve is to merge the following arrays based on key :
{"Entities":{"submenu_id":"Parents","submenu_label":"parents"}}
{"Entities":{"submenu_id":"Insurers","submenu_label":"insurers"}}
{"Users":{"submenu_id":"New roles","submenu_label":"newrole"}}
{"Users":{"submenu_id":"User - roles","submenu_label":"user_roles"}}
{"Users":{"submenu_id":"Roles - permissions","submenu_label":"roles_permissions"}}
{"Accounting":{"submenu_id":"Input accounting data","submenu_label":"new_accounting"}}
Which needs to output like this:
[{"item_header":"Entities"},
{"list_items" :
[{"submenu_id":"Parents","submenu_label":"parents"},
{"submenu_id":"Insurers","submenu_label":"insurers"}]
}]
[{"item_header":"Users"},
{"list_items" :
[{"submenu_id":"New roles","submenu_label":"newrole"}
{"submenu_id":"User - roles","submenu_label":"user_roles"}
{"submenu_id":"Roles - permissions","submenu_label":"roles_permissions"}]
}]
[{"item_header":"Accounting"},
{"list_items" :
[{"submenu_id":"Input accounting data","submenu_label":"new_accounting"}]
}]
I have been trying all kinds of things for the last two hours, but each attempt returned a different format as the one required and thus failed miserably. Somehow, I couldn't figure it out.
Do you have a construction in mind to get this job done?
I would be very interested to hear your approach on the matter.
Thanks.
$input = array(
'{"Entities":{"submenu_id":"Parents","submenu_label":"parents"}}',
'{"Entities":{"submenu_id":"Insurers","submenu_label":"insurers"}}',
'{"Users":{"submenu_id":"New roles","submenu_label":"newrole"}}',
'{"Users":{"submenu_id":"User - roles","submenu_label":"user_roles"}}',
'{"Users":{"submenu_id":"Roles - permissions","submenu_label":"roles_permissions"}}',
'{"Accounting":{"submenu_id":"Input accounting data","submenu_label":"new_accounting"}}',
);
$input = array_map(function ($e) { return json_decode($e, true); }, $input);
$result = array();
$indexMap = array();
foreach ($input as $index => $values) {
foreach ($values as $k => $value) {
$index = isset($indexMap[$k]) ? $indexMap[$k] : $index;
if (!isset($result[$index]['item_header'])) {
$result[$index]['item_header'] = $k;
$indexMap[$k] = $index;
}
$result[$index]['list_items'][] = $value;
}
}
echo json_encode($result);
Here you are!
In this case, first I added all arrays into one array for processing.
I thought they are in same array first, but now I realize they aren't.
Just make an empty $array=[] then and then add them all in $array[]=$a1, $array[]=$a2, etc...
$array = '[{"Entities":{"submenu_id":"Parents","submenu_label":"parents"}},
{"Entities":{"submenu_id":"Insurers","submenu_label":"insurers"}},
{"Users":{"submenu_id":"New roles","submenu_label":"newrole"}},
{"Users":{"submenu_id":"User - roles","submenu_label":"user_roles"}},
{"Users":{"submenu_id":"Roles - permissions","submenu_label":"roles_permissions"}},
{"Accounting":{"submenu_id":"Input accounting data","submenu_label":"new_accounting"}}]';
$array = json_decode($array, true);
$intermediate = []; // 1st step
foreach($array as $a)
{
$keys = array_keys($a);
$key = $keys[0]; // say, "Entities" or "Users"
$intermediate[$key] []= $a[$key];
}
$result = []; // 2nd step
foreach($intermediate as $key=>$a)
{
$entry = ["item_header" => $key, "list_items" => [] ];
foreach($a as $item) $entry["list_items"] []= $item;
$result []= $entry;
}
print_r($result);
I would prefer an OO approach for that.
First an object for the list_item:
{"submenu_id":"Parents","submenu_label":"parents"}
Second an object for the item_header:
{"item_header":"Entities", "list_items" : <array of list_item> }
Last an object or an array for all:
{ "Menus: <array of item_header> }
And the according getter/setter etc.
The following code will give you the requisite array over which you can iterate to get the desired output.
$final_array = array();
foreach($array as $value) { //assuming that the original arrays are stored inside another array. You can replace the iterator over the array to an iterator over input from file
$key = /*Extract the key from the string ($value)*/
$existing_array_for_key = $final_array[$key];
if(!array_key_exists ($key , $final_array)) {
$existing_array_for_key = array();
}
$existing_array_for_key[count($existing_array_for_key)+1] = /*Extract value from the String ($value)*/
$final_array[$key] = $existing_array_for_key;
}

Categories