解析一个字符串然后发布

时间:2013-06-04 01:33:50

标签: php parsing post

我将数据从另一个服务发布为字符串:             heading="firstname","lastname"&user_1382926="Mike",Smith"&user_1383059="Sonny","Williams"&user_1303EM000014="Mike","Jones"

我在解析这个问题时迷失了,因为user_ *可能是任何东西,但它并不一致。

我试过了:

$query  = explode('&', 'heading="firstname","lastname"&user_1382926="Mike",Smith"&user_1383059="Sonny","Williams"&user_1303EM000014="Mike","Jones"');
$params = array();

foreach( $query as $param ){
list($name, $value) = explode('=', $param);
echo $params[urldecode($name)][] = urldecode($value);
}

但它只是给了我:

"firstname","lastname""Mike",Smith""Sonny","Williams""Mike","Jones"

我希望能够将其发布到:

$firstname  = $_POST['firstname'];
$lastname   = $_POST['lastname']; 
$stmt = $mysqli->prepare("INSERT INTO usertest (firstname,lastname) VALUES (?,?)"); 
$stmt->bind_param('ss', $firstname, $lastname);
$stmt->execute(); 

如何解析这个以便正确发布?

4 个答案:

答案 0 :(得分:1)

非常粗糙,但这是我到达的结果:

$names = array();
$string = 'heading="firstname","lastname"&user_1382926="Mike","Smith"&user_1383059="Sonny","Williams"&user_1303EM000014="Mike","Jones"';

$arr = explode("&",$string);

foreach($arr as $key_values){
    if(substr($key_values,0,5) == 'user_'){
        $piecies = explode("=",$key_values);
        foreach($piecies as $key=>$val){
            if($key%2==0){
                continue;
            }
            preg_match_all('/"(.*?)","(.*?)"/',$val,$first_last_name);
            $names[] = array('firstname'=>$first_last_name[1],'lastname'=>$first_last_name[2]);
        }
    }
}

echo '<pre>',print_r($names),'</pre>';

foreach($names as $name){
    $firstname  = $name['firstname'];
    $lastname   = $name['lastname']; 
    $stmt = $mysqli->prepare("INSERT INTO usertest (firstname,lastname) VALUES (?,?)"); 
    $stmt->bind_param('ss', $firstname, $lastname);
    $stmt->execute(); 
}

注意:我在原始字符串中添加了史密斯("Mike","Smith")之前的双引号,因为我希望它在OP中缺失。

答案 1 :(得分:0)

首先你的字符串似乎缺少引号。见

  &user_1382926="Mike",Smith"

其次,使用爆炸似乎是一个坏主意,因为你会爆炸&amp;和=引用字段的内部。

我通常采用的方式是状态机。使用正则表达式(参见PHP - split String in Key/Value pairs)要简单得多。

您尝试匹配的语言似乎是:

  • 键可以由1个或多个字母数字或下划线字符组成。
  • 值是逗号分隔的引用字符串列表
  • 键和值以等号分隔
  • 键值对由&amp;
  • 分隔

获取键值配对的正则表达式是:

$regex = '/&?([^=]+)=([^&]+)/';
preg_match_all($regex, $header, $r);
$result = array_combine($r[1], $r[2]);

$ result中的第一个条目将包含键'header'和值'“firstname”,“lastname”'。

现在我们只需要将结果中的值从字符串转换为字符串列表。

foreach ($result as $key => $value) {
    $regex = '("[^"]+")';
    preg_match_all($regex, $value, $r);
    $result[$key] = $r;
}

这缺少一些边缘情况,例如值内的转义引号,但在大多数情况下都适用。

在你的例子中它产生:

  Array
  (
    [heading] => Array
        (
            [0] => "firstname"
            [1] => "lastname"
        )

    [user_1382926] => Array
        (
            [0] => "Mike"
            [1] => "Smith"
        )

    [user_1383059] => Array
        (
            [0] => "Sonny"
            [1] => "Williams"
        )

    [user_1303EM000014] => Array
        (
            [0] => "Mike"
            [1] => "Jones"
        )
  )

答案 2 :(得分:0)

我讨厌这样的答案,但你对这篇文章有什么控制权吗?这些数据很乱,根本不符合标准。

它应该看起来像这样......如你所知:

firstname=bob&lastname=smith&user=123654&heading=someheading&...

现在,即使你有多个人进入一个帖子,也可以 - 只要它们有序。那看起来像......

firstname=bob&lastname=smith&firstname=william&lastname=jones

当您获得这样的数据时,您可以像下面那样解析它:

foreach($_POST['firstname'] as $k => $v){
     echo "Key: ".$k;
     echo " Value: ".$v;
}

会打印出来 键:名字值:bob键:名字值:威廉

答案 3 :(得分:0)

由于作者写道:“是的,我想将其发布到外部网址。”“不幸的是我无法控制它。这是问题的一部分。” 我想你的问题可以像这样解决。

警告:这不是最佳解决方案,它可能有效,但会导致开销。请尝试更好地解释您想要达到的目标。

$url = 'user_1382926="Mike","Smith"&user_1383059="Sonny","Williams"&user_1303EM000014="Mike","Jones"';
    $query  = explode('&', str_replace('"', '', urldecode($url)));

    $params = array();

    foreach( $query as $param )
    {
        list($name, $value) = explode('=', $param);
        $q = explode(',', $value);
        $params[$name] = 'firstname=' . $q[0] . '&lastname=' . $q[1];
    }

    $url = 'http://domain.com/post.php';


    $ch = curl_init();

    foreach ( $params as $current )
    {
        curl_setopt($ch,CURLOPT_URL, $url);
        curl_setopt($ch,CURLOPT_POST, 2);
        curl_setopt($ch,CURLOPT_POSTFIELDS, $current);

        $result = curl_exec($ch);
    }

    curl_close($ch);