Regex & PHP $_POST - php

all. I have a problem retrieving certain POST values incoming to a script I have set up. The POST keys are not changeable as they come from a request from PayPal. However I need some way to get these values dynamically.
When a person purchases multiple items, I get POST values returned such as:
item_name=foo
item_name1=bar
item_name2=blah
I was thinking that I'll have to do some sort of Regular Expression to get the values, but I'm not sure about the syntax, or if it's even possible to use RegEx on a superglobal.
maybe something like:
$exp = "/item_name(d+)/";
foreach($_POST as $key => $val)
{
preg_match($exp,$key,$match);
}
As you can tell, I'm really bad with RegEx's. Any help would be greatly appreciated. :)
--EDIT--
Okay, there's two main POST keys that I need to catch. The problem is there may be any number (positive integer) after the key name:
item_name
item_name1
item_name2
item_number
item_number1
item_number2
But the ending digit can go all the way to 10, depending upon the number of products purchased.
What I need to do is grab the values for each one of these, and add each item_number to a string to be inserted into a transaction table in my database.
Perhaps something closer to:
$itms = '';
foreach($_POST as $key => $val)
{
if (strpos($key, 'item_name') === 0)
{
if($itms = '')
{
$itms = $val;
}
else
{
$itms .= ','.$val;
}
}
// don't really want to do it like this because i'd have to do it 10 times
if (strpos($key, 'item_name1') === 0)
{
if($itms = '')
{
$itms = $val;
}
else
{
$itms .= ','.$val;
}
}
}
// insert into DB after collecting all values
And yes, this is from an IPN.
--EDIT 2 --
This is what I have for my IPN listener script:
case 'ipnHandle' :
$header = '';
$retArray = array();
$req = 'cmd=_notify-validate';
foreach ($_POST as $key => $value)
{
$value = urlencode(stripslashes($value));
$req .= "&$key=$value";
}
// post back to PayPal system to validate
$header .= "POST /cgi-bin/webscr HTTP/1.0\r\n";
$header .= "Content-Type: application/x-www-form-urlencoded\r\n";
$header .= "Content-Length: " . strlen($req) . "\r\n\r\n";
$fp = fsockopen ('ssl://www.sandbox.paypal.com', 443, $errno, $errstr, 30);
// assign posted variables to local variables
$item_name = $_POST['item_name'];
$item_number = $_POST['item_number'];
$payment_status = $_POST['payment_status'];
$payment_amount = $_POST['mc_gross'];
$payment_currency = $_POST['mc_currency'];
$txn_id = $_POST['txn_id'];
$receiver_email = $_POST['receiver_email'];
$payer_email = $_POST['payer_email'];
if (!$fp)
{
$err_msg = 'Could not open the Paypal site to Verify Transaction';
}
else
{
fputs ($fp, $header . $req);
while (!feof($fp))
{
$res = fgets ($fp, 1024);
if (strcmp ($res, "VERIFIED") == 0)
{
if($_POST['receiver_email'] == "chaoskreator#gmail.com")
{
if($_POST['payment_status'] == 'Completed')
{
$sql = 'SELECT transaction_id FROM '.SHOP_TRANS_TABLE.' WHERE transaction_pid = '.$_POST['txn_id'];
$result = $db->sql_query($sql);
$row = $db->sql_fetchrow($result);
if($row != 0 && $row != null)
{
$id_exp = '/^item_number(\d*)$/';
$qty_exp = '/^quantity(\d*)$/';
$price_exp = '/^mc_gross(\d*)$/';
$items = array();
$qtys = array();
$prices = array();
foreach($_POST as $key => $val)
{
$match = Array();
if(preg_match($id_exp, $key, $match))
{
$items[] = $val;
}
if(preg_match($qty_exp, $key, $match))
{
$qtys[] = $val;
}
if(preg_match($price_exp, $key, $match))
{
$prices[] = $val;
}
}
}
}
}
$itmStr = implode(",", $items);
$qtyStr = implode(",", $qtys);
$priceStr = implode(",", $prices);
$data = '';
$file = "verifyLog.txt";
$fh = fopen($file, "a+");
foreach($_POST as $key => $value)
{
if($data == '')
{
$data = '['.$key.']'.$value;
}
else
{
$data .= ',['.$key.']'.$value;
}
}
$data .= "\r\n".$itmStr."\r\n".$qtyStr."\r\n".$priceStr;
fwrite($fh, $data);
fclose($fh);
}
else if (strcmp ($res, "INVALID") == 0)
{
$data = '';
$file = "failLog.txt";
$fh = fopen($file, "a+");
foreach($_POST as $value)
{
if($data == '')
{
$data = '['.$key.']'.$value;
}
else
{
$data .= ',['.$key.']'.$value;
}
}
fwrite($fh, $data);
fclose($fh);
}
}
fclose ($fp);
}
break;
And this is the response ans logged to verifyLog.txt, with no comma-delimited string appended to the end...:
[test_ipn]1,[payment_type]instant,[payment_date]20:47:04 Apr 19, 2011 PDT,[payment_status]Completed,[payer_status]verified,[first_name]John,[last_name]Smith,[payer_email]buyer#paypalsandbox.com,[payer_id]TESTBUYERID01,[business]seller#paypalsandbox.com,[receiver_email]seller#paypalsandbox.com,[receiver_id]TESTSELLERID1,[residence_country]US,[item_name]something,[item_number]AK-1234,[item_name1]somethingElse,[item_number1]1234346dfg,[quantity]1,[quantity1]1,[shipping]8.50,[tax]2.02,[mc_currency]USD,[mc_fee]0.44,[mc_gross]15.34,[mc_gross_1]12.34,[mc_handling]2.06,[mc_handling1]1.67,[mc_shipping]3.02,[mc_shipping1]1.02,[txn_type]cart,[txn_id]4420347,[notify_version]2.4,[custom]xyz123,[invoice]abc1234,[charset]windows-1252,[verify_sign]XXXXXXXXXXXX
This is drinving me nuts. lol

If you are just matching a prefix, then regular expressions are arguably overkill. A simple string comparison such as the following would allow you to identify the items
if (strpos($key, 'item_name') === 0) {
// $key starts with item_name....
}

The below code will check each one to see if it is one of the item keys, and grab the ID if so. Your example showed one that did not have the digits on it, and since I am not familiar with the Paypal stuff you're dealing with, I went ahead and set the ID to 0 when such a match is made.
<?php
$exp = '/^item_name(\d*)$/';
$values = Array();
foreach( $_POST as $key => $val )
{
$match = Array();
//If this is one of the item name variables
if( preg_match( $exp, $key, $match ) )
{
//then put it into the array of captured values
$values[] = $val;
}
}
$commaSeparatedForDb = implode( ',', $values );

// find all the matching field names
$fields_to_do = preg_grep('/^item_name\d*$/', $_POST);
// loop over them
foreach($files_to_do as $field) {
// extract what # they have
$id = substr($field, 9); // either blank, or 1,2,3,4,etc...
$name = $_POST["item_name$id"];
$number = $_POST["item_number$id"];
... do stuff ...
}

try this
$i = 0;
do {
$key = 'item_name';
if ($i > 0) {
$key .= $i; // append number to key if > 0
}
if (isset($_POST[$key])) {
echo "found $key => ".$_POST[$key];
// do something with it
}
$i++;
} while (isset($_POST[$key]));
BASED ON EDITED QUESTION ABOVE
if($_POST['payment_status'] == 'Completed')
{
$sql = 'SELECT transaction_id FROM '.SHOP_TRANS_TABLE.' WHERE transaction_pid = '.$_POST['txn_id'];
$result = $db->sql_query($sql);
// where is sql error checking, what if this sql has failed??
$row = $db->sql_fetchrow($result);
if($row != 0 && $row != null) {
// have you checked to see if the code is ever reaching this point?
// is it possible your database row doesn't exist
// this part here looks fine for extracting $_POST values
$id_exp = '/^item_number(\d*)$/';
$qty_exp = '/^quantity(\d*)$/';
$price_exp = '/^mc_gross(\d*)$/';
// maybe we should declare these arrays earlier.
// if this test fails, "if($row != 0 && $row != null) "
// you are still imploding the arrays below even though they haven't been declared
$items = array();
$qtys = array();
$prices = array();
foreach($_POST as $key => $val) {
// no need to store the matches as you aren't using them anyway
// $match = Array();
// changed 3x if statements to elseif
// this is not essential and won't effect the outcomes
// but is good practice as there is no point testing all 3 cases if first/second case already matches
if(preg_match($id_exp, $key)) {
$items[] = $val;
} elseif(preg_match($qty_exp, $key)) {
$qtys[] = $val;
} elseif (preg_match($price_exp, $key)) {
$prices[] = $val;
}
}
}
$itmStr = implode(",", $items);
$qtyStr = implode(",", $qtys);
$priceStr = implode(",", $prices);

Related

PHP script to create new csv from another csv after rearranging the data

I have a csv with following structure:
And I need the output csv as follows:
That means taking the faetures from each column and put it in the single row.
I am using php office to fetch and write the csv. I have written the following:
if ( false === $handle = fopen('../../../3b.csv', 'r') )
throw new Exception('File open failed.');
$headers = fgetcsv($handle);
$row = '';
$row = array();
$data = '';
$data = array();
while ( false !== $fields = fgetcsv($handle) ) {
$fields = array_combine($headers, $fields);
foreach($fields as $key=>$value){
if($key!='sku'){
if($value==''){
continue;
}
}
$row[$key] = $value;
}
if(sizeof($row)==1){
unset($row['sku']);
}
$row = array_filter( $row );
$data[] = $row;
}
$data = array_filter($data);
$use_keys = ['sku','AC Rating','color','Feature','Finish','Grade','Installation Location','Installation Method','Plank Style','Size','Specie','Tile Format','Warranty','Wear Layer','Width','LifeStyle',
'Material','Style','Thickness','Appearance','PEIRating','ProtectionRating'];
foreach($data as $key=>$value){
$new_arr = [];
foreach($use_keys as $apk_item) {
$new_value = '';
if (isset($data[$key][$apk_item])) {
$new_value = str_replace(",","|",$data[$key][$apk_item]);
}
$new_arr[$apk_item] = $new_value;
}
$data[$key] = $new_arr;
}
$data = array_filter($data, 'array_filter');
$final_array = array();
foreach ($data as $features) {
$product = array('feature' => '');
foreach ($features as $key => $feature) {
if ($key == 'sku') {
$product['sku'] = $feature;
}
else {
if($feature!=''){
$product['feature'] .= $key;
$product['value'] .= $feature;
}
}
}
$final_array[] = $product;
}
$final_array = array_filter($final_array);
$table = '<table border="1" id="csvtable">
<thead><tr><th>sku</th><th>feature</th><th>value</th></tr></thead>
<tbody>';
foreach($final_array as $value){
$sku = $value["sku"];
$combinedfeature = explode(",", $value['feature']);
foreach($combinedfeature as $single){
$table .= '<tr><td width="20%">'.$sku.'</td><td width="40%">'.$single['feature'].'</td><td width="40%">'.$single['value'].'</td></tr>';
}
}
$table .= '</tbody></table>';
print_r($table);
It's giving wrong output. How can I do this? Anyone can help, please?
A much more compact method would be to read the input and write out the target file in one loop.
This code reads in each line, combines it with the header and then extracts the sku (and removes it from the details). Then loops over the remaining details, and if there is a value to output it writes the output to the result file.
As each value may also be a comma separated list, this uses explode() to split them into individual items and writes them out as separate parts...
$inputFile = "a.csv";
$outputFile = "a1.csv";
$inputHandle = fopen($inputFile, 'r');
$outputHandle = fopen($outputFile, 'w');
$headers = fgetcsv($inputHandle);
fputcsv($outputHandle, ["sku", "feature", "value" ]);
while ( false !== $fields = fgetcsv($inputHandle) ) {
$fields = array_combine($headers, $fields);
$sku = $fields['sku'];
unset($fields['sku']);
foreach ( $fields as $name => $field ) {
if (!empty(trim($field))) {
$subFields = explode(",", $field );
foreach ( $subFields as $value ) {
fputcsv($outputHandle, [$sku, $name, $value]);
}
}
}
}
fclose($inputHandle);
fclose($outputHandle);

PHP function - How to take three fields and perform and action when the first, 2nd and last field are the same but on different rows of a file

I have file that is delimetered by a comma like below
Big2,red,0,Y
Big2,blue,0,N
Big2,green,1,N
Big6,red,0,Y
Big6,blue,0,N
Big6,green,1,N
Big6,yellow,0,Y
Big6,black,0,Y
Following is the code I used to read the file
$file_content = explode("\n",(file_get_contents("inven.csv")));
foreach ($file_content as $key => $value) {
$value = str_replace(array('\'', '"'), '', $value);
$line_records = explode(',', $value);
$reference = trim($line_records[0]);
$option = trim($line_records[1]);
$quantity = trim($line_records[2]);
$discontinued = trim($line_records[3]);
}
I want to check for the following condition and perform some action
If the 1st, 2nd and 4th field are the same for all lines
If all "Big2" rows have the 3rd field = 0 and the 4th field = Y
Hope this solves your problem
$references = $options =$quantities = $status = array();
$file_content = explode("\n",(file_get_contents("inven.csv")));
foreach ($file_content as $key => $value) {
$value = str_replace(array('\'', '"'), '', $value);
$line_records = explode(',', $value);
$references[] = trim($line_records[0]);
echo end($references);
$options[] = trim($line_records[1]);
echo end($options);
$quantities[] = trim($line_records[2]);
echo end($quantities);
$status[] = trim($line_records[3]);
echo end($status);
}
$flag = true;
foreach(array_combine($references, $quantities, $status) as $ref => $quantity => $stat) { // foreach line throws and error
if($ref == 'Big2') {
if($quantity != 0 || $stat != 'Y'){
$flag = false;
break;
}
}
}
if (count(array_unique($references)) === 1 && count(array_unique($options))==1 && count(array_unique($status))==1) {
//Do action if the 1st, 2nd and 4th field are the same for all lines
}
if ($flag) {
//Do action if all "Big2" rows have the 3rd field = 0 and the 4th field = Y
}

Trim Error occuring in PHP

I am designing an application and in my modal came across a strange error
<b>Warning</b>: trim() expects parameter 1 to be string, array given in <b>C:\xampp\htdocs\gurukul\demo2\controller\routemgmt\route_mgmt.php</b> on line <b>7</b><br />
61
As far as I can understand its passing an array instead of string in trim. Below is the modal where its showing the error lies :
<?php
include_once dirname(dirname(dirname(__FILE__))) . "/const.php";
include_once PHP_PATH . "/config1.php";
include_once CONFIG_PATH.'/modal/routemgmt/route_mgmt.php';
function sanitize($input) {
return htmlspecialchars(trim($input));
}
// Sanitize all the incoming data
$sanitized = array_map('sanitize', $_POST);
$reason = $sanitized['reason'];
if($reason == "insert"){
$staffs = [];
$stops = [];
$name = $sanitized['rname'];
$code = $sanitized['rcode'];
$desc = $sanitized['rdesc'];
$vnum = $sanitized['vnum'];
$stf = $_POST['staff'];
$st = isset($_POST['stops'])? $_POST['stops']: [];
$st = [];
// foreach($staffs as $staff){
// $stf[] = array_map('sanitize', $staff);
// }
// if(isset($stops)){
// foreach($stops as $stop){
// $st[] = array_map('sanitize', $stop);
// }
// }
$val = insertRoute($conn,$name, $code, $desc, $vnum, $stf, $stops);
echo $val;
}
if($reason == "view"){
$id = $sanitized['id'];
$val = [];
$val = viewRoute($conn,$id);
echo json_encode($val);
}
if($reason == "edit"){
$stf = [];
$stp = [];
$id = $sanitized['pkid'];
$name = $sanitized['rname'];
$code = $sanitized['rcode'];
$desc = $sanitized['rdesc'];
$vnum = $sanitized['vnum'];
$estaffs = $_POST['estaff'];
$estops = $_POST['estops'];
$edel = $_POST['del'];
foreach($estaffs as $val){
$stf[] = array_map('sanitize', $val);
}
foreach($estops as $val){
$stp[] = array_map('sanitize', $val);
}
$cnt = 0;$n_stp = [];
for($i = 0; $i<sizeof($stp); $i++){
if($stp[$i]['stat'] != "Exist"){
$n_stp[$cnt] = $stp[$i];
$cnt++;
}
}
$val = editValues($conn,$id, $name, $code, $desc, $vnum, $stf, $n_stp, $edel);
echo $val;
}
if($reason == "delRoute"){
$id = $sanitized['id'];
$val = delRoute($conn,$id);
echo $val;
}
Can someone please guide me how can I resolve this ? Tried few debugging steps but didnt get succeded
You could rewrite your sanitize function as:
function sanitize($input) {
if (is_array($input))
return array_map('sanitize', $input);
else
return htmlspecialchars(trim($input));
}
That way it will handle a value passed to it which is an array.
Your $_POST variable probably contains some kind of array. Either figure out what you're posting by checking the output of var_dump($input) inside your sanitize function or change it to this:
function sanitize($input) {
return htmlspecialchars(trim((string) $input));
}
if you just want it to work.

how to loop through a multi dimensional associative array the correct way

i am at the point in my script where i want to insert data into my database after looping through an associative array.
the code works so far but since i am new to programming i wish to know if there is a more efficient alternative way of doing what i am doing, since i will be adding more elseif's when my array grows, and also the fact that i am querying my database after every iteration.
foreach($database as $key=>$value) {
foreach($value as $field => $cell){
if ($field =='itemid') {
echo "the item id is $cell";
$col1 = $cell ;
}
elseif ($field =='title') {
echo "the title is $cell";
$col2 = $cell;
}
elseif ($field =='starttime') {
echo "the start time is $cell";
$col3 = $cell;
}
}
$query = "INSERT INTO cordless_drill(itemid,title,starttime) VALUES ('$col1','$col2','$col3')";
mysqli_query($dbc,$query);
}
// here is a code snippet
// $db = new MyDbClass();
// $db->insert->('cordless_drill', $cell); // where $cell is holding key/value pairs
public function insert($table, $obj) {
return $this->query("INSERT INTO ".$table.$this->obj2KeyValue($obj));
}
private function obj2KeyValue($obj) {
$i = count($obj);
$k = ""; $v = "";
$init = false;
$sql = " SET ";
while (list($k, $v) = each($obj)) {
if ($v != "") {
$v = $this->mysqli->real_escape_string($v);
if ($init) $sql .= ", ";
else $init = true;
$sql .= $k.'="'.$v.'"';
}
}
return $sql;
}
public function query($q) {
if ($this->debug) {
$logFile = "sql_query.log";
$handle = fopen($logFile, "a+");
$data = $q."\n";
fwrite($handle, $data);
fclose($handle);
}
return $this->mysqli->query($q);
}

Export mysql data as CSV in php

In my code, I need to preserve all commas in each fields from the mysql table in CSV Export...
For this I used the double quotes to all fields. This code is perfectly running in the Linux System.. While running the same code in windows, double quotes also displaying in Exported CSV file.. What is the problem in this? can anyone tell me why it is happening like this?
function arrayToCSV($array, $header_row = true, $col_sep = ",", $row_sep = "\n", $qut = '"',$pgeTyp ="")
{
/*col_sep =htmlentities($col_sep);
$row_sep =htmlentities($row_sep);
$qut =htmlentities($qut);*/
if (!is_array($array) or !is_array($array[0])) return false;
//Header row.
if ($header_row)
{
foreach ($array[0] as $key => $val)
{
//Escaping quotes.
$key = str_replace($qut, "$qut$qut", $key);
$output .= $col_sep.$qut.$key.$qut;
}
$output = substr($output, 1)."\n".$row_sep;
}
//Data rows.
foreach ($array as $key => $val)
{
$tmp = '';
foreach ($val as $cell_key => $cell_val)
{
if($pgeTyp!="twitter" && $pagTyp!="jigsaw" && $pgeTyp=="")
$timeValue = #checkTimeStamp($cell_val);
else $timeValue = '';
if($timeValue=="True")
{
$cell_val = str_replace($qut, "$qut$qut", convert_time_zone($cell_val,'d-M-y h:i:s'));
}
else
{
$cell_val = str_replace($qut, "$qut$qut", $cell_val);
}
$tmp .= $col_sep.$qut.$cell_val.$qut;
}
$output .= substr($tmp, 1).$row_sep;
}
return $output;
}
Function call is,
$dbResult1[] =array('url_twitter_userid' => $selecttwittermainFtch['url_twitter_userid'],'url_tweet_name' => "$url_tweet_name",'url_twitter_uname' => "$url_twitter_uname",'url_twitter_url' => $selecttwittermainFtch['url_twitter_url'],'url_twitter_location' => "$url_twitter_location",'url_twitter_followers' => $selecttwittermainFtch['url_twitter_followers'],'url_twitter_following' => $selecttwittermainFtch['url_twitter_following'],'url_modified_on' => $modifiedon);
echo arrayToCSV($dbResult1, true, ", ", "\n", '','twitter');
Try this:
function sqlQueryToCSV($filename, $query)
{
$result = mysql_query($query);
$num_fields = mysql_num_fields($result);
$headers = array();
for ($i = 0; $i < $num_fields; $i++) {
$headers[] = mysql_field_name($result , $i);
}
$fp = fopen(mysql_real_escape_string(getcwd().'\\'.$filename), 'w');
if ($fp) {
fputcsv($fp, $headers);
while ($row = mysql_fetch_array($result)) {
$arrayValues = array();
foreach ($headers as $header)
{
$arrayValues[] = $row[$header];
}
fputcsv($fp, $arrayValues);
}
}
fclose($fp);
}
Source: http://forums.exchangecore.com/topic/907-function-to-convert-mysql-query-to-csv-file-with-php/
When you are opening it in Windows with whatever program (Guessing Excel), you should be able to specify what characters you use to delimit/surround the fields. It's probably just assuming that you are just wanting to use commas to separate but ignoring the double quotes surrounding them.

Categories