Регулярное выражение и PHP $_POST

#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 я добавил несколько комментариев к вашему исправленному коду и добавил к своему ответу