使用数组值搜索PHP数组,然后更新匹配数组中的其他数组值

时间:2016-05-18 06:10:48

标签: php arrays serialization

我有一个存储在WordPress MySQL数据库Meta字段中的字符串作为数组数组的序列化字符串,如下所示:

a:4:{i:0;a:8:{s:19:"ab-variation-letter";s:1:"B";s:18:"ab-variation-title";s:6:"bbbbbb";s:28:"ab-variation-wysiwyg-editor-";s:12:"bbbbbbbbbbbb";s:29:"ab-variation-conversion-count";s:0:"";s:18:"ab-variation-views";s:0:"";s:23:"ab-variation-start-date";s:0:"";s:21:"ab-variation-end-date";s:0:"";s:19:"ab-variation-winner";s:0:"";}i:1;a:8:{s:19:"ab-variation-letter";s:1:"C";s:18:"ab-variation-title";s:5:"ccccc";s:28:"ab-variation-wysiwyg-editor-";s:17:"ccccccccccccccccc";s:29:"ab-variation-conversion-count";s:0:"";s:18:"ab-variation-views";s:0:"";s:23:"ab-variation-start-date";s:0:"";s:21:"ab-variation-end-date";s:0:"";s:19:"ab-variation-winner";s:0:"";}i:2;a:8:{s:19:"ab-variation-letter";s:1:"D";s:18:"ab-variation-title";s:8:"dddddddd";s:28:"ab-variation-wysiwyg-editor-";s:1:"d";s:29:"ab-variation-conversion-count";s:0:"";s:18:"ab-variation-views";s:0:"";s:23:"ab-variation-start-date";s:0:"";s:21:"ab-variation-end-date";s:0:"";s:19:"ab-variation-winner";s:0:"";}i:3;a:8:{s:19:"ab-variation-letter";s:1:"E";s:18:"ab-variation-title";s:8:"eeeeeeee";s:28:"ab-variation-wysiwyg-editor-";s:30:"eeeeeee eeeeeeeeeeeee eeeeeeee";s:29:"ab-variation-conversion-count";s:0:"";s:18:"ab-variation-views";s:0:"";s:23:"ab-variation-start-date";s:0:"";s:21:"ab-variation-end-date";s:0:"";s:19:"ab-variation-winner";s:0:"";}}

当我在上面反序列化该字符串时,它看起来如下所示......

array (
  0 => 
  array (
    'ab-variation-letter' => 'B',
    'ab-variation-title' => 'bbbbbb',
    'ab-variation-wysiwyg-editor-' => 'bbbbbbbbbbbb',
    'ab-variation-conversion-count' => '',
    'ab-variation-views' => '',
    'ab-variation-start-date' => '',
    'ab-variation-end-date' => '',
    'ab-variation-winner' => '',
  ),
  1 => 
  array (
    'ab-variation-letter' => 'C',
    'ab-variation-title' => 'ccccc',
    'ab-variation-wysiwyg-editor-' => 'ccccccccccccccccc',
    'ab-variation-conversion-count' => '',
    'ab-variation-views' => '',
    'ab-variation-start-date' => '',
    'ab-variation-end-date' => '',
    'ab-variation-winner' => '',
  ),
  2 => 
  array (
    'ab-variation-letter' => 'D',
    'ab-variation-title' => 'dddddddd',
    'ab-variation-wysiwyg-editor-' => 'd',
    'ab-variation-conversion-count' => '',
    'ab-variation-views' => '',
    'ab-variation-start-date' => '',
    'ab-variation-end-date' => '',
    'ab-variation-winner' => '',
  ),
  3 => 
  array (
    'ab-variation-letter' => 'E',
    'ab-variation-title' => 'eeeeeeee',
    'ab-variation-wysiwyg-editor-' => 'eeeeeee eeeeeeeeeeeee eeeeeeee',
    'ab-variation-conversion-count' => '',
    'ab-variation-views' => '',
    'ab-variation-start-date' => '',
    'ab-variation-end-date' => '',
    'ab-variation-winner' => '',
  ),
)

基于上面的这个数组数组。我希望能够搜索具有ab-variation-letter' => 'C'的数组,然后能够更新该匹配数组上的任何其他数组键值。完成后,我需要重新序列化为一个字符串,以便我可以将它再次保存回数据库表。

我想在下面构建这个PHP函数,以便能够获取我的序列化数组数组,并搜索这些数组中的数组,其中键/值与传入的$array_key字符串相匹配,然后更新另一个数组keyvalue在同一个数组中,然后再重新整理整个事物。

function updateAbTestMetaData($post_id, $meta_key, $meta_value, $array_key, $new_value){

    //get serialized meta from DB
    $serialized_meta_data_string = 'a:4:{i:0;a:8:{s:19:"ab-variation-letter";s:1:"B";s:18:"ab-variation-title";s:6:"bbbbbb";s:28:"ab-variation-wysiwyg-editor-";s:12:"bbbbbbbbbbbb";s:29:"ab-variation-conversion-count";s:0:"";s:18:"ab-variation-views";s:0:"";s:23:"ab-variation-start-date";s:0:"";s:21:"ab-variation-end-date";s:0:"";s:19:"ab-variation-winner";s:0:"";}i:1;a:8:{s:19:"ab-variation-letter";s:1:"C";s:18:"ab-variation-title";s:5:"ccccc";s:28:"ab-variation-wysiwyg-editor-";s:17:"ccccccccccccccccc";s:29:"ab-variation-conversion-count";s:0:"";s:18:"ab-variation-views";s:0:"";s:23:"ab-variation-start-date";s:0:"";s:21:"ab-variation-end-date";s:0:"";s:19:"ab-variation-winner";s:0:"";}i:2;a:8:{s:19:"ab-variation-letter";s:1:"D";s:18:"ab-variation-title";s:8:"dddddddd";s:28:"ab-variation-wysiwyg-editor-";s:1:"d";s:29:"ab-variation-conversion-count";s:0:"";s:18:"ab-variation-views";s:0:"";s:23:"ab-variation-start-date";s:0:"";s:21:"ab-variation-end-date";s:0:"";s:19:"ab-variation-winner";s:0:"";}i:3;a:8:{s:19:"ab-variation-letter";s:1:"E";s:18:"ab-variation-title";s:8:"eeeeeeee";s:28:"ab-variation-wysiwyg-editor-";s:30:"eeeeeee eeeeeeeeeeeee eeeeeeee";s:29:"ab-variation-conversion-count";s:0:"";s:18:"ab-variation-views";s:0:"";s:23:"ab-variation-start-date";s:0:"";s:21:"ab-variation-end-date";s:0:"";s:19:"ab-variation-winner";s:0:"";}}';

    //un-serialize meta data string
    $meta_data_arrays = unserialize($serialized_meta_data_string);

    // search array of arrays $meta_data_arrays for array that has a key == $array_key // 'ab-variation-letter' === 'D'

    // update the value of any other key on that matching array

    // re-serialize all the data with the updated data

}

最终结果应该允许我找到包含键'ab-variation-letter' === 'C'的数组,并使用键'ab-variation-title'更新该匹配数组中的键/值,并将其当前值从'ccccc'更新为{ {1}}然后将整个数组数组重新序列化回原始字符串,只更新更新的数组数据/

2 个答案:

答案 0 :(得分:1)

也许抛出一个可以利用调用本身的递归函数可以派上用场:

function replaceArrayKeyValue(array &$arr, $whereKey, $whereValue, $replacement) {
  $matched = false;
  $keys = array_keys($arr);

  for ($i = 0; $i < count($keys); $i++)
  {
    $key = $keys[$i];
    if (is_string($arr[$key])) {
      if ($key === $whereKey && $arr[$key] === $whereValue) {
        if (is_array($replacement)) {
          $arr = array_replace_recursive($arr, $replacement);
        } else {
          $arr[$key] = $replacement;
        }
        $matched = $key;
        break;
      }
    } else if (is_array($arr[$key])) {
      $m = replaceArrayKeyValue($arr[$key], $whereKey, $whereValue, $replacement);
      if ($m !== false) {
        $matched = $key.'.'.$m;
        break;
      }
    }
    unset($key);
  }

  unset($keys);
  return $matched;
}

使用上面的函数,您将通过源代码数组{$arr),即您要查找的密钥($whereKey),它应匹配的值($whereValue)和替换值($replacement)。

如果$replacement是一个数组,我有一个array_replace_recursive来执行递归替换,允许您传递您想要对数组进行的更改。例如,在您的情况下:

$data = unserialize(...);
$matchedKey = replaceArrayKeyValue($data, 'ab-variation-letter', 'C', [
    'ab-variation-title' => 'My New Title'
]);
$serialized = serialize($data);

如果您不希望更改在任何嵌套的子数组中进一步发生,则可以将其替换为array_recursive

使用此功能时,会直接修改$data数组。函数的结果是该值的关键路径的联合字符串,在本例中为:

echo $matchedKey; // Result: 1.ab-variation-letter

如果你echo print_r($data, true),你会得到预期的结果:

Array (
    [0] => Array( ... )
    [1] => Array
        (
            [ab-variation-letter] => C
            [ab-variation-title] => My New Title
            [ab-variation-wysiwyg-editor-] => ccccccccccccccccc
            [ab-variation-conversion-count] =>
            [ab-variation-views] =>
            [ab-variation-start-date] =>
            [ab-variation-end-date] =>
            [ab-variation-winner] =>
        )
    [2] => Array( ... )
    [3] => Array( ... )
)

答案 1 :(得分:0)

我在使用下面的代码玩了一些之后就开始工作了。打开其他版本也谢谢

$serialized_meta_data_string = 'a:4:{i:0;a:8:{s:19:"ab-variation-letter";s:1:"B";s:18:"ab-variation-title";s:6:"bbbbbb";s:28:"ab-variation-wysiwyg-editor-";s:12:"bbbbbbbbbbbb";s:29:"ab-variation-conversion-count";s:0:"";s:18:"ab-variation-views";s:0:"";s:23:"ab-variation-start-date";s:0:"";s:21:"ab-variation-end-date";s:0:"";s:19:"ab-variation-winner";s:0:"";}i:1;a:8:{s:19:"ab-variation-letter";s:1:"C";s:18:"ab-variation-title";s:5:"ccccc";s:28:"ab-variation-wysiwyg-editor-";s:17:"ccccccccccccccccc";s:29:"ab-variation-conversion-count";s:0:"";s:18:"ab-variation-views";s:0:"";s:23:"ab-variation-start-date";s:0:"";s:21:"ab-variation-end-date";s:0:"";s:19:"ab-variation-winner";s:0:"";}i:2;a:8:{s:19:"ab-variation-letter";s:1:"D";s:18:"ab-variation-title";s:8:"dddddddd";s:28:"ab-variation-wysiwyg-editor-";s:1:"d";s:29:"ab-variation-conversion-count";s:0:"";s:18:"ab-variation-views";s:0:"";s:23:"ab-variation-start-date";s:0:"";s:21:"ab-variation-end-date";s:0:"";s:19:"ab-variation-winner";s:0:"";}i:3;a:8:{s:19:"ab-variation-letter";s:1:"E";s:18:"ab-variation-title";s:8:"eeeeeeee";s:28:"ab-variation-wysiwyg-editor-";s:30:"eeeeeee eeeeeeeeeeeee eeeeeeee";s:29:"ab-variation-conversion-count";s:0:"";s:18:"ab-variation-views";s:0:"";s:23:"ab-variation-start-date";s:0:"";s:21:"ab-variation-end-date";s:0:"";s:19:"ab-variation-winner";s:0:"";}}';

$update_on_key = 'ab-variation-title';
$ab_version = 'C';
$new_value = 'new variation title on variation C';

$new_data = updateMetaArrayData($serialized_meta_data_string, $update_on_key, $ab_version, $new_value);

echo '<pre>';
echo $new_data;


function updateMetaArrayData($serialized_meta_data_string, $update_on_key, $ab_version, $new_value){
    $new_meta_data_arrays = array();

    //un-serialize meta data string
    $meta_data_arrays = unserialize($serialized_meta_data_string);

    foreach($meta_data_arrays as $key => $value){
        $new_meta_data_arrays[$key] = $value;
        if(isset($value['ab-variation-letter']) && $value['ab-variation-letter'] == $ab_version){
            $new_meta_data_arrays[$key][$update_on_key] = $new_value;
        }
    }

    echo '<pre>';
    print_r($new_meta_data_arrays);

    $new_serialized_meta = serialize($new_meta_data_arrays);
    return $new_serialized_meta;
}