Setting custom field values on old WordPress posts in bulk via WP-CLI

If you are a WordPress user that takes advantage of custom fields and WP-CLI… this may interest you.

Let’s say you’re using ACF field groups on posts in a certain category. You have a new custom field with a default value you’ve added to that field group. You’ve already modified the template to conditionally show a piece of UI based on that field value. Finally, you realize that now you’re going to have to open each post in the editor, one at a time, to save it in order to get that field value set.

Or… maybe there’s a way to script it?

In my situation, I only have about ten posts that need this treatment, but if I was looking at manually updating each post to include that new default value across hundreds of posts… /shudder

I decided to research & teach myself the steps I’d need to work through if I ever find myself in that situation.

Where are ACF values set in the database?

ACF field values are stored in the wp_postmeta table.

custom fields in wp_postmeta

There are actually two rows in post_meta. One is the actual value. The other is a reference.

Test: Update one post via WP-CLI

We’re going to try using wp post update1.

wp post update 4045 --kjzz_has_audio=1 --_kjzz_has_audio=field_59038b5c9457b

Successfully updating meta on a specified post

Ok, that’s a good start.

How can we affect only posts in X category?

Thankfully, in my situation, all the posts I need to affect belong to a specific category. I can grab a list of the post IDs with this:

wp post list --category_name=category-slug --format=ids

The whole command

So, now I need to combine the two.

Like most situations in life, I can’t be the first person to be in this boat. Someone has to have written about this in the past, right?

After a little searching, I ran across Updating Multiple Posts’ Meta | Mika Epstein. Check out Mike Little’s suggestion in the comments… That looks promising!

And this is what I ended up with:

for id in $(wp post list --category_name=arizona-business --fields=ID --format=ids); do wp post update $id --kjzz_has_audio=1 --_kjzz_has_audio=field_59038b5c9457b; done

BAM!

Successfully updating meta on a specified post

Victory Almost.

After inspecting a few of the records in Sequel Pro, it looked like the ones that already had those custom fields were ‘updated’ (to the same value), but the ones that didn’t have those custom fields yet did not actually get new meta added.

Looks like we’re actually going to need wp post meta and we’ll need to update/add each meta key/value individually.

Victory!

for id in $(wp post list --category_name=arizona-business --fields=ID --format=ids); do wp post meta update $id kjzz_has_audio 1; done

then…

for id in $(wp post list --category_name=arizona-business --fields=ID --format=ids); do wp post meta update $id _kjzz_has_audio field_59038b5c9457b; done

BAM!


… Now I’m wondering if I could have used:

for id in $(wp post list --category_name=arizona-business --fields=ID --format=ids); do wp post meta update $id kjzz_has_audio 1 && wp post meta update $id _kjzz_has_audio field_59038b5c9457b; done

  1. Nope. Close… but that doesn’t add the custom fields if they’re not there ↩︎

Leave a Reply