【问题标题】:Parsing a string to then post解析一个字符串然后发布
【发布时间】:2013-06-04 01:33:49
【问题描述】:

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

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

【问题讨论】:

  • +1 表示尝试;这些天非常罕见。
  • 您要将其发布到外部 URL 吗?
  • 是的,我想将其发布到外部 URL。
  • 如果你对每个用户名都做一个 POST,这会导致很大的开销。

标签: php parsing post


【解决方案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 中丢失。

【讨论】:

  • 这行得通,我所做的唯一更改是:foreach($names as $name){ $firstname = $name['firstname'][0]; $lastname = $name['lastname'][0]; $stmt = $mysqli-&gt;prepare("INSERT INTO loantest (firstname,lastname) VALUES (?,?)"); $stmt-&gt;bind_param('ss', $firstname, $lastname); $stmt-&gt;execute(); }
【解决方案2】:

我讨厌这样的答案,但是您对发给您的帖子有任何控制权吗?这些数据一团糟,根本不符合标准。

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

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 键:名字 值:william

【讨论】:

  • 不幸的是我无法控制它。这是问题的一部分。
【解决方案3】:

由于作者写道:“是的,我想将其发布到外部 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);

【讨论】:

    【解决方案4】:

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

      &user_1382926="Mike",Smith"
    

    其次,使用explode 似乎是个坏主意,因为你会在引用的字段中爆炸& 和=。

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

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

    • 键可以由 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"
            )
      )
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-07-10
      • 1970-01-01
      • 1970-01-01
      • 2016-04-25
      • 2013-08-09
      • 1970-01-01
      相关资源
      最近更新 更多