代码之家  ›  专栏  ›  技术社区  ›  Svish

PHP:如何将key=value文件快速拆分为关联数组

  •  0
  • Svish  · 技术社区  · 15 年前

    当你发送一个PDT交易ID回贝宝,你会得到一个交易数据列表。它在第一行成功,然后是key=value对列表。每行一对。例如:

    SUCCESS
    business=paypal@example.com
    charset=windows-1252
    custom=
    first_name=Alice
    handling_amount=0.00
    invoice=NN0005
    item_name=Bear
    item_number=BEAR05
    last_name=Foobar
    mc_currency=SEK
    mc_fee=13.00
    mc_gross=250.00
    payer_email=bob@example.com
    payer_id=UC9DXVX7GRSTN
    payer_status=unverified
    payment_date=09:08:06 Oct 18, 2010 PDT
    payment_fee=
    payment_gross=
    payment_status=Completed
    payment_type=instant
    protection_eligibility=Ineligible
    quantity=1
    receipt_id=2479-2605-1192-2880
    receiver_email=paypal@example.com
    receiver_id=8Y670ENTB8BY6
    residence_country=NO
    shipping=0.00
    tax=0.00
    transaction_subject=Bear
    txn_id=1PH815997L239283J
    txn_type=web_accept
    

    检查第一行是否成功,然后将其转换为关联数组的好的、快速的和干净的方法是什么?我能做到,而且很有效,但我很好奇是否有更好或更干净的方法来做,因为我最终得到的并不总是那么好。注意,有些键也没有任何值。

    array(
        'business' => 'paypal@example.com',
        'charset' => 'windows-1252',
        'custom' => NULL,
        'first_name' => Alice,
    
        // And so on
    
    );
    

    顺序无关紧要。

    谢谢你的建议!现在测试他们。顺便说一下,把字符串分成几行也是我的问题之一。忘了具体说明。注意,有些方法已经考虑到了这一点,有些则没有考虑到,这可能会产生影响,因为某些方法需要先分成几行,然后再分成两对,而另一些方法则可以一块吃掉整件东西。

    我还应该提到,空的结果是空的,这是一种奖励,但可能不是一个要求。他们在我的版本中也没有这样做,也没什么大不了的。


    基准结果

    我很好奇我应该在这里选择什么,所以我基准我应该如何做不同的部分。我自己有各种各样的想法,从这里和其他地方也得到了一些。当我找到了我能做到的最快速度时,我创建了一个基准,并将它与迄今为止的所有答案进行了对比。对于那些跳过拆分或检查成功的用户,我添加了一个 explode 以及 strpos 相应检查。我还将urldecode添加到所有解决方案中,除了@dynamism处理得非常好。不管怎样,结果如下:

    Benchmark results

    基准测试是使用 codebench Kohana 3

    <?php defined('SYSPATH') or die('No direct script access.');
    
    /**
     * Test various methods of checking for SUCCESS
     *
     * @package  PayPal
     * @category PDT
     * @author  Torleif Berger
     */
    class Bench_ProcessPDT extends Codebench
    {
        public $description = 'Various ways of checking that a string starts with SUCCESS';
    
        public $loops = 100000;
    
    
        public function bench_mine($subject)
        {
            if(strpos($subject, 'SUCCESS') === 0)
            {
                $subject = urldecode(substr($subject, 7));
                preg_match_all('/^([^=]++)=(.*+)/m', $subject, $result, PREG_PATTERN_ORDER);
                $result = array_combine($result[1], $result[2]);
    
                return array(count($result), array_shift($result), array_shift($result));
            }
            return FALSE;
        }
    
        // http://stackoverflow.com/questions/3964219/3964308#3964308
        public function bench_dynamism_substr($subject)
        {
            if(substr($subject, 0, 7) == 'SUCCESS')
            {
                $subject = substr_replace($subject, '', 0, 7);
                $subject = str_replace(array("\n", "\r", "\r\n"), '&', $subject);
                parse_str($subject, $result);
    
                return array(count($result), array_shift($result), array_shift($result));
            }
            return FALSE;
        }
    
        // http://stackoverflow.com/questions/3964219/3964308#3964308
        public function bench_dynamism_strpos($subject)
        {
            if(strpos($subject, 'SUCCESS') === 0)
            {
                $subject = substr_replace($subject, '', 0, 7);
                $subject = str_replace("\r\n", '&', $subject);
                parse_str($subject, $result);
    
                return array(count($result), array_shift($result), array_shift($result));
            }
            return FALSE;
        }
    
        // http://stackoverflow.com/questions/3964219/3964520#3964520
        public function bench_mellowsoon($subject)
        {
            $subject = urldecode($subject);
    
            $lines = explode("\r\n", $subject);
            $lines = array_map('trim', $lines);
            $status = array_shift($lines);
            if($status == 'SUCCESS')
            {
                $result = array();
                foreach($lines as $line)
                {
                    list($key, $value) = explode('=', $line, 2);
                    $result[$key] = $value;
                }
                return array(count($result), array_shift($result), array_shift($result));
            }
    
            return FALSE;
        }
    
        // http://stackoverflow.com/questions/3964219/3964265#3964265
        public function bench_amber($subject)
        {
            if(strpos($subject, 'SUCCESS') === 0)
            {
                $subject = explode("\r\n", urldecode($subject));
                array_shift($subject);  // Remove is empty
    
                $result = array();
                foreach($subject as $line)
                {
                    $bits = explode('=', $line);
                    $field_name = array_shift($bits);
                    $field_contents = implode('=', $bits);
                    $result[$field_name] = $field_contents;
                }
                return array(count($result), array_shift($result), array_shift($result));
            }
            return FALSE;
        }
    
        // http://stackoverflow.com/questions/3964219/3964366#3964366
        public function bench_GigaWatt($subject)
        {
            if(strpos($subject, 'SUCCESS') === 0)
            {
                $subject = explode("\r\n", urldecode($subject));
    
                $result = array();
                foreach($subject as $line)
                {
                    if (strpos($line, "=") === FALSE)
                        continue;
    
                    list($var, $value) = explode("=", trim($line));
                    $result[$var] = empty($value) ? NULL : $value;
                }
                return array(count($result), array_shift($result), array_shift($result));
            }
            return FALSE;
        }
    
        // http://stackoverflow.com/questions/3964219/3964366#3964366
        public function bench_GigaWatt2($subject)
        {
            if(strpos($subject, 'SUCCESS') === 0)
            {
                $subject = explode("\r\n", urldecode($subject));
    
                $result = array();
                foreach($subject as $line)
                {
                    if (strpos($line, "=") === FALSE)
                        continue;
    
                    list($var, $value) = explode("=", trim($line));
                    $result[$var] = $value;
                }
                return array(count($result), array_shift($result), array_shift($result));
            }
            return FALSE;
        }
    
        // http://stackoverflow.com/questions/3964219/3964323#3964323
        public function bench_dvhh($subject)
        {
            if(strpos($subject, 'SUCCESS') === 0)
            {
                $subject = explode("\r\n", urldecode($subject));
    
                $result = array();
                foreach($subject as $line)
                {
                    $lineData = preg_split("/\s*=\s*/", $line);
                    if(count($lineData) == 2)
                    {
                        $result[$lineData[0]] = $lineData[1];
                    }
                }
                return array(count($result), array_shift($result), array_shift($result));
            }
            return FALSE;
        }
    
    
        public $subjects = array
        (
            "SUCCESS\r\nbusiness=paypal@business.example.com\r\ncharset=windows-1252\r\ncustom=\r\nfirst_name=Alice\r\nhandling_amount=0.00\r\ninvoice=AF000001\r\nitem_name=Stuffed bear\r\nitem_number=BEAR05\r\nlast_name=Foobar\r\nmc_currency=USD\r\nmc_fee=2.00\r\nmc_gross=20.00\r\npayer_email=alice.foobar@example.com\r\npayer_id=UC9DXVX7GRSTN\r\npayer_status=unverified\r\npayment_date=09:08:06 Oct 18, 2010 PDT\r\npayment_fee=\r\npayment_gross=\r\npayment_status=Completed\r\npayment_type=instant\r\nprotection_eligibility=Ineligible\r\nquantity=1\r\nreceipt_id=2479-2605-1192-2880\r\nreceiver_email=paypal@example.com\r\nreceiver_id=8Y670ENTB8BY6\r\nresidence_country=USD\r\nshipping=0.00\r\ntax=0.00\r\ntransaction_subject=Bear\r\ntxn_id=1PH815997L239283J\r\ntxn_type=web_accept",
    
            "FAIL\r\nError: 4003",
    
            "INVALID",
        );
    }
    

    如果有人有任何进一步的改进建议,请告诉我:)

    6 回复  |  直到 15 年前
        1
  •  0
  •   tonyhb    15 年前

    这是我用5行来做的:

    // Is this a successful post?
    if( substr($paypal, 0, 7) == 'SUCCESS')
    {
        $paypal = substr_replace($paypal, '', 0, 7);
        $paypal = str_replace(array("\n", "\r", "\r\n"), '&', $paypal);
        parse_str($paypal, $response_array);
    }
    

    查看回发 $paypal 成功,如果删除第一行,则将换行符替换为 & parse_str ,已排序。输出在 $response_array

    和Amber一样的问题 NULL 显示为 '' .

    编辑:还有一个警告:如果数组键中有任何特殊字符(出于某种奇怪的原因,可能是 . _ .

        2
  •  2
  •   Amber    15 年前

    分开第一行,检查它,然后用这个来抓取其余的:

    foreach($response_lines as $line) {
        $bits = explode('=', $line);
        $field_name = array_shift($bits);
        $field_contents = implode('=', $bits);
        $fields[$field_name] = $field_contents;
    }
    

    之后 $fields 将是你寻找的阵列。(一个注释:响应中没有值的项将具有 '' 而不是 NULL

        3
  •  0
  •   dvhh    15 年前

    使用 http://www.php.net/manual/en/function.preg-split.php

    foreach($lines as $line) {
        $lineData = preg-split("\s*=\s*",$line);
        if(count($lineData)==2) {
             $result[$lineData[0]] = $lineData[1];
        }
    }
    
        4
  •  0
  •   Mr. Llama    15 年前

    foreach($response as $line) {
        if (strpos($line, "=") === FALSE) { continue; }   // Skip the line if there's no assignment action going on.
        list($var, $value) = explode("=", trim($line));   // Get the parts on either side of the "=".
        $result[$var] = (empty($value) ? NULL : $value);  // Assign the value to the result array, making the value NULL if it's empty.
    }
    
        5
  •  0
  •   mellowsoon    15 年前

    加上我的2美分,因为目前发布的一些解决方案过于聪明,或不是100%正确。

    $lines = explode("\n", $paypal_response);
    $lines = array_map('trim', $lines);
    $status = array_shift($lines);
    if ($status != 'SUCCESS') {
        // Transaction was not successful
    }
    $values = array();
    foreach($lines as $line) {
        list($key, $value) = explode('=', $line, 2);
        $values[$key] = $value;
    }
    
        6
  •  0
  •   Itay Moav -Malimovka    15 年前

    下面是一个更复杂的解决方案:

    //$result=the result from paypal
    parse_str(str_replace(PHP_EOL,'&',$result),$result);
    var_dump($result);
    
    推荐文章