最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

post meta - How can I convert postmeta from unserialized to serialized?

programmeradmin4浏览0评论

I'm replacing 2 fields that were previously set up with ACF and saved separately. Instead of those, I want to have 1 piece of serialized postmeta.

So, I'm going from

meta_key: old_key_1, meta_value: value_1
meta_key: old_key_2, meta_value: value_2

to

meta_key: new_meta_key, meta_value: a:2:{i:0;s:7:"value_1";i:1;s:7:"value_2";}

(I'm not querying on these, just displaying on single posts, so I'd prefer to have a single entry in the database that holds each post's meta.) Because I have several hundred posts to update, I'd like to do this programmatically, either in phpMyAdmin or PHP, but I'm not sure what queries to run.

Question 1 - this part is solved

How do I update field_1 to contain serialized data?

I added a temporary function to update the meta key and serialize the meta value of the first field:

<?php add_action('admin_init', 'convert_double_meta');
function convert_double_meta() {
    global $wpdb;
    $first_records = $wpdb->get_results(
        $wpdb->prepare("SELECT * FROM wp_postmeta WHERE meta_key = 'field_1'")
    );
    foreach($first_records as $record) {
        // Serialize the meta value by passing it as an array
        update_post_meta($record->post_id, 'field_1', array(0 => $record->meta_value));
        // Update the meta key
        $updated = $wpdb->update(
            'wp_postmeta',
            array(
                'meta_key' => 'new_meta_key'
            ),
            array('meta_id' => $record->meta_id)
        );
    }
} ?>

Question 2 - still unsolved

How can I merge the data from old_key_2 into the serialized value for new_meta_key? (And if there's an easier way to complete all of this, I'm quite open to doing different steps to achieve the same result.)

I'm replacing 2 fields that were previously set up with ACF and saved separately. Instead of those, I want to have 1 piece of serialized postmeta.

So, I'm going from

meta_key: old_key_1, meta_value: value_1
meta_key: old_key_2, meta_value: value_2

to

meta_key: new_meta_key, meta_value: a:2:{i:0;s:7:"value_1";i:1;s:7:"value_2";}

(I'm not querying on these, just displaying on single posts, so I'd prefer to have a single entry in the database that holds each post's meta.) Because I have several hundred posts to update, I'd like to do this programmatically, either in phpMyAdmin or PHP, but I'm not sure what queries to run.

Question 1 - this part is solved

How do I update field_1 to contain serialized data?

I added a temporary function to update the meta key and serialize the meta value of the first field:

<?php add_action('admin_init', 'convert_double_meta');
function convert_double_meta() {
    global $wpdb;
    $first_records = $wpdb->get_results(
        $wpdb->prepare("SELECT * FROM wp_postmeta WHERE meta_key = 'field_1'")
    );
    foreach($first_records as $record) {
        // Serialize the meta value by passing it as an array
        update_post_meta($record->post_id, 'field_1', array(0 => $record->meta_value));
        // Update the meta key
        $updated = $wpdb->update(
            'wp_postmeta',
            array(
                'meta_key' => 'new_meta_key'
            ),
            array('meta_id' => $record->meta_id)
        );
    }
} ?>

Question 2 - still unsolved

How can I merge the data from old_key_2 into the serialized value for new_meta_key? (And if there's an easier way to complete all of this, I'm quite open to doing different steps to achieve the same result.)

Share Improve this question edited Jan 16, 2020 at 17:37 WebElaine asked Jan 16, 2020 at 15:33 WebElaineWebElaine 9,8041 gold badge17 silver badges28 bronze badges 1
  • Do you need to preserve the old keys? In other words, should the new array use the old keys as their indexes? – Jacob Peattie Commented Jan 17, 2020 at 0:47
Add a comment  | 

1 Answer 1

Reset to default 0

I would probably take an alternative route and let the serialization happen at the end after the data was already merged like in the example below.

So first query meta data for both old keys. Then merge the old data into an array (regular or associative) with post ID as key. Then use the resulting array in a loop which uses update_post_meta to let it handle the serialization. Finally some $wpdb query to wipe the data with the old keys from the database.

This might not be the most efficient way to do this, but if you're executing this only once, then I don't think it matters too much.

add_action('admin_init', 'convert_meta_data');
function convert_meta_data() {    
  $data = query_old_data( old_keys() );

  $data = merge_old_data( $data ) ;

  update_meta_with_new_key( $data, 'new_meta_key' );

  delete_data_with_old_keys( old_keys() );
}

function old_keys() {
  return array(
    'field_1',
    'field_2'
  );
}

function query_old_data( array $old_keys ) {
  $data = array();
  global $wpdb;
  foreach( $old_keys as $old_key ) {
    $data[$old_key] = $wpdb->get_results(
      $wpdb->prepare("SELECT * FROM wp_postmeta WHERE meta_key = {$old_key}")
    );
  }  
  return $data;
}

function merge_old_data( array $data ) {
  $out = array();
  foreach ($data as $old_key => $records) {
    foreach ($records as $record) {
      $out[$record->post_id][$old_key] = maybe_unserialize($record->meta_value); 
      // I don't know what happens, if some of the data in the resulting array was serialized and some not, so lets make sure everything is unserialized     
    }    
  }
  return $out;
}

function update_meta_with_new_key( array $data, string $key ) {
  foreach ($data as $post_id => $meta_array) {
    update_post_meta($post_id, $key, $meta_array); // handles serialization
  }
}

function delete_data_with_old_keys( array $old_keys ) {
  // not too sure about this
  $sql = "meta_key = " . implode('OR ', $old_keys);
  global $wpdb;
  $wpdb->delete( 'wp_postmeta', $sql);
}
发布评论

评论列表(0)

  1. 暂无评论