#php #regex #post
#php #регулярное выражение #Публикация
Вопрос:
ВСЕ. У меня проблема с получением определенных значений POST, поступающих в настроенный мной скрипт. Ключи POST не могут быть изменены, поскольку они поступают из запроса от PayPal. Однако мне нужен какой-то способ получить эти значения динамически.
Когда пользователь покупает несколько товаров, я получаю возвращаемые значения POST, такие как:
item_name=foo
item_name1=bar
item_name2=blah
Я думал, что мне нужно будет выполнить какое-то регулярное выражение, чтобы получить значения, но я не уверен в синтаксисе, или вообще возможно ли использовать RegEx для суперглобального.
может быть, что-то вроде:
$exp = "/item_name(d )/";
foreach($_POST as $key => $val)
{
preg_match($exp,$key,$match);
}
Как вы можете сказать, я действительно плохо разбираюсь в регулярных выражениях. Буду признателен за любую помощь. 🙂
—РЕДАКТИРОВАТЬ—
Хорошо, есть два основных ключа POST, которые мне нужно перехватить. Проблема в том, что после имени ключа может быть любое число (положительное целое):
item_name
item_name1
item_name2
item_number
item_number1
item_number2
Но конечная цифра может доходить до 10, в зависимости от количества приобретенных продуктов.
Что мне нужно сделать, это получить значения для каждого из них и добавить каждый item_number к строке, которая будет вставлена в таблицу транзакций в моей базе данных.
Возможно, что-то более близкое к:
$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
И да, это из IPN.
—РЕДАКТИРОВАТЬ 2 — Это то, что у меня есть для моего скрипта прослушивания IPN:
case 'ipnHandle' :
$header = '';
$retArray = array();
$req = 'cmd=_notify-validate';
foreach ($_POST as $key => $value)
{
$value = urlencode(stripslashes($value));
$req .= "amp;$key=$value";
}
// post back to PayPal system to validate
$header .= "POST /cgi-bin/webscr HTTP/1.0rn";
$header .= "Content-Type: application/x-www-form-urlencodedrn";
$header .= "Content-Length: " . strlen($req) . "rnrn";
$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 amp;amp; $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 .= "rn".$itmStr."rn".$qtyStr."rn".$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;
И это ответ, который был зарегистрирован в verifyLog.txt без добавления строки, разделенной запятой, в конце…:
[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
Это сводит меня с ума. лол
Комментарии:
1. Откройте для себя массивы сами. Кстати, так и должно быть
d
, а неd
. И*
, не
2. Чему ты пытаешься соответствовать?
3. Вам нужно узнать, что такое массив и что делает foreach. Ваши правки в коде все дальше уходят от ответа, в то время как были опубликованы совершенно правильные ответы..
Ответ №1:
Если вы просто сопоставляете префикс, то регулярные выражения, возможно, излишни. Простое сравнение строк, такое как следующее, позволило бы вам идентифицировать элементы
if (strpos($key, 'item_name') === 0) {
// $key starts with item_name....
}
Комментарии:
1. Это имеет гораздо больше смысла, но как я буду обрабатывать каждый из экземпляров? Должен ли я был бы сделать
if(strpos($key, 'item_name') === 0){ if(strpos($key, 'item_name1') === 0) { //do this if you have a second product } }
2. Возможно, я неправильно понимаю, но вы не обязаны. Поскольку вы просматриваете весь
$_POST
массив, у$key
и$value
есть все, что вам нужно. Жестко кодировать нечего. Сделайте то, что вам нужно сделать для каждого элемента внутри логики, которую я опубликовал.3. Извините, случайно нажал enter при публикации ранее. Позвольте мне вернуться и отредактировать исходное сообщение, чтобы показать больше деталей.
4. я предполагаю, что это из IPN, вам просто нужно выполнить foreach() foreach ($_POST как $key => $ value)
Ответ №2:
Приведенный ниже код проверит каждый из них, чтобы увидеть, является ли он одним из ключей элемента, и, если да, получит идентификатор. Ваш пример показал, что в нем нет цифр, и, поскольку я не знаком с материалами Paypal, с которыми вы имеете дело, я пошел дальше и установил идентификатор равным 0, когда такое совпадение будет выполнено.
<?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 );
Комментарии:
1. Это именно то, что я пытался сделать изначально. Пожалуйста, смотрите ПРАВКУ 2 в исходном сообщении.
Ответ №3:
// find all the matching field names
$fields_to_do = preg_grep('/^item_named*$/', $_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 ...
}
Комментарии:
1.
$id = substr($field, 8);
На самом деле не было бы$id = substr($field, 9);
, потому что оно должно начинаться после 2-го ‘e’, 9-го символа в строке?2. Хммм… С этим тоже не повезло. Похоже, я обречен. 🙁
Ответ №4:
попробуйте это
$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]));
НА ОСНОВЕ ОТРЕДАКТИРОВАННОГО ВОПРОСА ВЫШЕ
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 amp;amp; $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 amp;amp; $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);
Комментарии:
1. Я действительно пробовал что-то подобное однажды раньше и с треском провалился. Возможно, я смогу адаптировать это к своим потребностям. Я попробую.
2. в этой строке была опечатка, извините, echo «найдено $key => «.$_POST[$key]; замените $ _POST[‘key’] на $ _POST[$key], хотя остальной код должен работать
3. @jason я добавил несколько комментариев к вашему исправленному коду и добавил к своему ответу