4

我有从另一个服务作为字符串发布的数据: 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

4 回答 4

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(); 
}

注意:我在您的原始字符串中的 Smith ( ) 之前添加了一个双引号"Mike","Smith",因为我希望它只是从 OP 中丢失。

于 2013-06-04T01:50:20.877 回答
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;
}

将打印 Key: firstname Value:bob Key: firstname Value: william

于 2013-06-04T01:55:38.577 回答
0

首先,您的字符串似乎缺少引号。看

  &user_1382926="Mike",Smith"

其次,使用explode 似乎是个坏主意,因为您将在引用字段内爆炸& 和=。

我通常会采用的方式是状态机。使用正则表达式(请参阅 PHP - 在键/值对中拆分字符串)要简单得多。

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

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

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

$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"
        )
  )
于 2013-06-04T01:44:32.637 回答
0

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

警告:这不是最好的解决方案,它可能会起作用,但会导致开销。请尝试更好地解释您想要归档的内容。

$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);
于 2013-06-04T02:04:06.413 回答