Hello I am performing a query with the paypal API and my question concerns an array and retrieving values for the key (which is dynamic) I know the query works and credentials are good, as the following array is returned:
array(2) {
["L_TRANSACTIONID0"]=>
string(17) "9FX81733DJ079610B"
["L_TRANSACTIONID1"]=>
string(17) "5E083945JC6368706"
["L_TRANSACTIONID2"]=>
string(17) "7SP75180Y9281954W"
}
I am wanting to break each key out in a foreach loop, but each key is dynamic (notice the count on each key).
How can this be accomplished in a foreach loop?
Thanks,
I just answered a similar question the other day, so potentially a duplicate. In any case, if this helps someone, 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.
As an example of how to use this, say you want to feed this into PHPExcel object, you could do so like so:
$response = your_curl_call($request);
$data = process_response($response);
$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
I'm trying to do a find replace of the json data below. I'm trying to replace "Consumer" with "CON", "Industrial" with "IND", and "Technology" with "TCH". Ideally, I would like to pass a function an array of finds (i.e., {"Consumer", "Industrial", "Technology"}) along with an array of replaces (i.e., {"CON", "IND", "TCH"}), or some other way to quickly define multiple find and replace pairs (there will be many more pairs than these 3). What is the best function to do this? Thanks, any help is appreciated.
[{"category":"Consumer","price":"18.9","number":"5"},{"category":"Industrial","price":"13.4","number":"4"},{"category":"Technology","price":"15.5","number":"3"}]
Here's a solution that goes through the json data object piece by piece (examining both key and values and replacing as possible only if the key/value is fully in the array of $replaces)
function replace(&$array, $replaces) {
foreach ($array as $k => $v) {
$new_k = replace_word($k, $replaces);
if (is_array($v)) {
replace($v, $replaces);
}
else {
$v = replace_word($v, $replaces);
}
$array[$new_k] = $v;
if ($new_k != $k) {
unset($array[$k]);
}
}
}
function replace_word($word, $replaces) {
if (array_key_exists($word, $replaces)) {
$word = str_replace($word, $replaces[$word], $word);
}
return $word;
}
/* TEST FUNCTIONS */
$json = '[{"category":"Consumer","price":"18.9","number":"5"},{"category":"Industrial","price":"13.4","number":"4"},{"category":"Technology","price":"15.5","number":"3"}]';
$replaces = array("category" => "cat", "Consumer" => "cons");
$json_data = json_decode($json, true);
var_dump($json_data);
replace($json_data, $replaces);
var_dump($json_data);
$json = json_encode($json_data);
preg_replace can take pattern and replacement as arrays.
http://php.net/manual/en/function.preg-replace.php
So, for example:
preg_replace(array('Consumer', 'Industrial', 'Technology'), array('CON', 'IND', 'TCH'), $json);
Note, however, that unless you're absolutely sure of the JSON you'll be getting it is probably better practice to parse the JSON and replace within the actual key/values.
Snippet:
$temp = array();
foreach ($data as $key => $value) {
// This line varies, from HTML to URLs, to anything in between
array_push($temp, "<b>$key:</b> $value");
}
$request = implode('<br/>', $temp); // Glue also varies depending on needs
unset($temp);
This is a getaway from the usual $string .= 'blah<br/>'. Never mind the rtrim.
Can anyone show me a better way to achieve above without use of a temp array and possibly without a loop? Bonus points for not using above code in a function, lambda acceptable though.
P.S. While writing this question I have found a wonderful http_build_query(). One down, one to go.
Edit:
What result should look like:
<b>Title: </b> Value</br>
<b>Title2: </b> Value2</br>
<b>Title3: </b> Value3
Or with different settings (not required, but shows possibility):
key=value&key2=value2&key3=value3
I am trying to improve my code, I use the above snippet everywhere.
My answer: There are some ways, but:
Loops & arrays are the best friends of any programmer.
They provide pretty good readability, reusability and generally are considered to be a right way for performing pretty much the same actions.
You may also take a look on array_map or array_walk. Less code, but it is a loop anyways.
array_walk($data, function($value, $key){
$temp[] = "<b>{$key}:</b> {$value}" ; //Shorthand for array_push is $arr[] = $value ;
}) ;
I suppose this is one way; yay for "one-liners":
$data = ...;
echo join("\n", array_map(function($key) use ($data) {
return sprintf('<b>%s:</b> %s',
htmlspecialchars($key, ENT_QUOTES, 'UTF-8'),
htmlspecialchars($data[$key], ENT_QUOTES, 'UTF-8')
);
}, array_keys($data)));
You basically map the keys using a closure that binds the original array as well so that you have access to both the key and value in each invocation.
I think you will prefere your solution:
$data = range('a', 'e'); // some data
$request = ''; // empty string
array_map(function($value, $key)use(&$request, $data){
static $i = 1;
if($i == count($data)){
$request .= "<b>$key:</b> $value";
}else{
$request .= "<b>$key:</b> $value<br/>";
}
$i++;
}, $data, array_keys($data));
echo $request;
Online demo
A solution with a loop but without $temp array:
$data = range('a', 'e'); // some data
$request = ""; // empty string
foreach ($data as $key => $value) {
$request .= "<b>$key:</b> $value<br/>"; // add to string
}
$request = substr($request,0,-5); // remove last <br/>
echo $request; //output
TL;DR
I have this data: var_export and print_r.
And I need to narrow it down to: http://pastebin.com/EqwgpgAP ($data['Stock Information:'][0][0]);
How would one achieve it? (dynamically)
I'm working with vTiger 5.4.0 CRM and am looking to implement a function that would return a particular field information based on search criteria.
Well, vTiger is pretty weakly written system, looks and feels old, everything comes out from hundreds of tables with multiple joins (that's actually not that bad) etc., but job is job.
The need arose from getting usageunit picklist from Products module, Stock Information block.
Since there is no such function as getField();, I am looking forward to filter it out from Blocks, that is actually gathering the information about fields also.
getBlocks(); then calls something close to getFields();, that again something close to getValues(); and so on.
So...
$focus = new $currentModule(); // Products
$displayView = getView($focus->mode);
$productsBlocks = getBlocks($currentModule, $displayView, $focus->mode, $focus->column_fields); // in theory, $focus->column_fields should/could be narrowed down to my specific field, but vTiger doesn't work that way
echo "<pre>"; print_r($productsBlocks); echo "</pre>"; // = http://pastebin.com/3iTDUUgw (huge dump)
As you can see, the array under the key [Stock Information:], that actually comes out from translations (yada, yada...), under [0][0] contains information for usageunit.
Now, I was trying to array_filter(); the data out from there, but only thing I've managed to get is $productsBlocks stripped down to only contain [Stock Information:] with all the data:
$getUsageUnit = function($value) use (&$getUsageUnit) {
if(is_array($value)) return array_filter($value, $getUsageUnit);
if($value == 'usageunit') return true;
};
$productsUsageUnit = array_filter($productsBlocks, $getUsageUnit);
echo "<pre>"; print_r($productsUsageUnit); echo "</pre>"; // = http://pastebin.com/LU6VRC4h (not that huge of a dump)
And, the result I'm looking forward to is http://pastebin.com/EqwgpgAP, that I've manually got by print_r($productsUsageUnit['Stock Information:'][0][0]);.
How do I achieve this? (dynamically...)
function helper($data, $query) {
$result = array();
$search = function ($data, &$stack) use(&$search, $query) {
foreach ($data as $entry) {
if (is_array($entry) && $search($entry, $stack) || $entry === $query) {
$stack[] = $entry;
return true;
}
}
return false;
};
foreach ($data as $sub) {
$parentStack = array();
if ($search($sub, $parentStack)) {
$result[] = $parentStack[sizeof($parentStack) - 2];
}
}
return $result;
}
$node = helper($data, 'usageunit');
print_r($node);
In my app I have a textarea, which my users are meant to enter data in the format:
Forename, Surname, YYYY-MM-DD, Company
Forename, Surname, YYYY-MM-DD, Company
on each line. My intention is to then loop through each row, exploding at the comma and trimming any white space.
I then need to pass the exploded array in to an associative array. I'm doing this manually at the moment, on the assumption that the user has entered the data in the correct order and format; which does work, but does rely on the user not messing things up.
What would you suggest as being a better way of doing this? I think the way I'm checking each index to see if it's empty or not seems rather clunky, as well as error prone.
Any suggestions or things to consider?
/************************************
* sample data from textarea:
* Name, Surname, 1980-02-22, Company
* Foo, Bar, 1970-05-12, Baz
************************************/
$data = preg_split('/\r\n|\n/', $_POST['data'],
-1, PREG_SPLIT_NO_EMPTY);
$item = array();
// loop through the data
foreach($data as $row) :
// trim and explode each line in to an array
$item[] = array_map('trim', explode(',', $row));
endforeach;
$k=0;
foreach($item as $user) :
$processed_data[$k]['first_name'] = !empty($user[0]) ? $user[0] : NULL;
$processed_data[$k]['last_name'] = !empty($user[1]) ? $user[1] : NULL;
if(!empty($user[2])) :
$dob = strtotime($user[2]);
if($dob) {
$processed_data[$k]['dob'] = $user[2];
} else {
$processed_data[$k]['dob'] = NULL;
}
else:
$processed_data[$k]['dob'] = NULL;
endif;
$processed_data[$k]['company'] = !empty($user[3]) ? $user[3] : NULL;
$k++;
endforeach;
// print_r($processed_data);
you are from the old school :)
Well, as you say above you expect the user to enter the data correctly in the text area. Well if your app is working currently in a robust system don't touch it, but otherwise you should consider to add different parameters in your post request (one for each filed you want to explode)...
you can do like this to solve the problem you have now:
// The algorithm below believe user send data correctly
// Forename, Surname, YYYY-MM-DD, Company
$names = array('first_name', 'last_name', 'dob', 'company_name');
$lines = explode("\n", $_POST['data']);
$result = array();
foreach ($lines as $ line)
{
$exploded_line = explode(",", $line);
$row = array();
foreach ($exploded_line as $key=>$item) { $row[$names[$key]]= trim($item); }
$result[]=$row;
}
// Now in result there is an array like this
// result[0][first_name]
// result[0][last_name]
// result[0][dob]
// result[0][company_name]
// result[1][first_name]
// [ ... ]
You can encapsulate the parsing and the validation into classes of it's own. Additionally you could do the same for the datastructure holding the tabular data.
class TableParser
{
private $string;
public function __construct($string)
{
$this->string = (string) $string;
}
public function parse()
{
$buffer = $this->string;
$rows = explode("\n", $buffer);
$rows = array_map('trim', $rows);
return $this->parseRows($rows);
}
private function parseRows(array $rows)
{
foreach($rows as &$row)
{
$row = $this->parseRow($row);
}
return $rows;
}
private function parseRow($row)
{
$keys = array('forename', 'surname', 'date', 'company');
$keyCount = count($keys)
$row = explode(',', $row, $keyCount);
if (count($row) != $keyCount)
{
throw new InvalidArgumentException('A row must have 4 columns.');
}
$row = array_map('trim', $row);
$row = array_combine($keys, $row);
return $row;
}
}
This parser is still quite rough. You can improve it over time, e.g. providing better error handling, given information which line failed and such. Such a component can then be easier integrated into your normal application flow as you can return that information back to the user so to enable her to make changes to the input.
Additionally you can put apart the validation into a second class and only do the exploding / trimming in the parser, but validation against count, specifying the array keys as well as validating the date format / value in the second class to keep things more apart.
How can I get the emails from this array?
array(16) {
[0]=> string(273) ""guid":"","contactId":"44","contactName":"_, atri","email":"atri_megrez#yahoo.com","emaillink":"http:\/\/mrd.mail.yahoo.com\/compose?To=atri_megrez%40yahoo.com","isConnection":false,"connection":"","displayImg":null,"msgrID":"atri_megrez","msgrStatus":"","isMsgrBuddy":122},"
[1]=> string(260) ""guid":"","contactId":"100","contactName":"afrin","email":"fida_cuty123#yahoo.com","emaillink":"http:\/\/mrd.mail.yahoo.com\/compose?To=fida_cuty123%40yahoo.com","isConnection":false,"connection":"","displayImg":null,"msgrID":"","msgrStatus":"","isMsgrBuddy":false},"
[2]=> string(258) ""guid":"","contactId":"101","contactName":"afrin","email":"waliyani#yahoo.com","emaillink":"http:\/\/mrd.mail.yahoo.com\/compose?To=waliyani%40yahoo.com","isConnection":false,"connection":"","displayImg":null,"msgrID":"","msgrStatus":"","isMsgrBuddy":false},"
}
It looks like each of the strings in that array is JSON data.
If you're using a modern version of PHP, you can use json_decode() to get to the data into a usable format.
foreach($array as $string) {
$json = json_decode($string);
echo "Email = {$json->email}\n";
}
If you could post an example of the data (eg: where it comes from, a properly formatted example of the print_r() output of the array) that would help, however from what I can gather this will get the emails from the array:
/* Make $array hold the given array */
$emails = array();
foreach($array as $contact){
$emails[] = $contact['email'];
}
// All emails
print_r($emails);
you can run a regexp on every array element. something like this: /"email":"(.+?)"/
$emails = array();
foreach ($array as $str)
{
if (preg_match('/"email":"(.+?)"/', $str, $matches))
{
$emails[] = $matches[1];
}
}