Skip to content

From Magic Fields 1.x to ACF, Part 9

Other posts in this series: Part 1; Part 2; Part 3; Part 4; Part 5; Part 6; Part 7; Part 8; Part 9 (this post)

I’ve made a few code changes since Part 9, mostly having to do with how sub-fields are created and named. There’s an additional underscore character created at the end of the name of a field, before the name of the subfield. So where I had:



foreach ( $churchlist as $postid=>$information ) {
//the $information is a new array, to be handled appropriately

Within each church’s block of entries I need to increment a number, so that some_field_here_1 becomes some_field_here_2 on the next duplicated field; then resets to some_field_here_1 for the next church.

$interior_designer = 1;
$renovations = 1;
$bells = 1;
$works_of_art = 1;
$windows = 1;
$architect = 1;
$style = 1;

This is really the core of how I’m going to replicate multiple instances of fields.

And then, working within the part of the loop for that specific church, I’m going to test each piece of the array. Here’s the first, the others work in exactly the same way.

if ( 'church_building_architectural_style' == $mf_field ) {
foreach ( $mf_value as $arrayvalue ) {
$insertkey = $mf_field . '__' . $interior_designer;
$fieldvalue = $field_codes[$insertkey];
$metainsert = "wp post meta add $postid ";
$metainsert .= "$insertkey escapeshellarg(json_encode($arrayvalue));
$metainsert .= ' --url= ';
$metainsert .= '--skip-themes --skip-plugins';
$meta_inserts[] = $metainsert;
$fieldmetainsert = "wp post meta add $postid ";
$fieldmetainsert .= "_" . "$insertkey $fieldvalue ";
$fieldmetainsert .= '--url= ';
$fieldmetainsert .= '--skip-themes --skip-plugins';
$meta_inserts[] = $fieldmetainsert;

In this case, the “architectural style” can contain multiple style, each part of the $mf_value. Also, note the escapeshellart(json_encode()) block. Since these values can contain newlines, apostrophes, quotes, etc., they have to be safely bundled into a json string in order to work.

Then, take the $mf_field variable (in this case, ‘church_building_architectural_style’), add a double underscore, and append the $interior_designer number — which starts out as 1.

$field_value as before looks up the “field_xxxxxxx” has generated by ACF which represents the Post ID of that custom field.

Then, $metainsert contains the wp-cli command. We’ll add post meta to this post (identified by number), identified by the $insertkey and the $arrayvalue (don’t forget the quotation marks). Since this is a multisite installation we must declare what the working URL is of the site. And we’ll skip themes and plugins because all they can do for us is throw spurious errors.

Then the second big variable, $fieldmetainsert, holds the _$insertkey that attaches this piece of metadata to the custom field that controls it.

And we’ll add both of those “wp post meta add” commands to the $meta_inserts table, and increment $interior_designer so that the second time this post encounters a designer it will be “2”.

These are all well and good for text, but for pictures?

There’s a different functionality that handles those. WP-CLI allows you to run an actual database query, using the credentials for your wordpress installation. This saves you from having to cope with establishing sessions and links to your server — the connection is already there.

What we want to end up with is a metavalue that is just a comma-separated list of post_ids, representing the images we’re using in this gallery. So,

elseif ( 'church_building_interior_pictures' == $mf_field ) {
$image_meta_array = array();
$imagestring = '';
foreach ( $mf_value as $imagelink ) {
$result = array();
if ( '' == $imagelink ) continue;
// get the image post ID
$clicmd = '';
$clicmd = 'wp db query "SELECT ID FROM wp_1776_posts WHERE guid LIKE ';
$clicmd .= "'%" . $imagelink . "' LIMIT 1;\"";
exec($clicmd, $result);
$image_meta_array[] = $result[1];
$imagestring = implode(',', $image_meta_array);
$metainsert = "wp post meta add $postid ";
$metainsert .= "church_building_interior_images $imagestring ";
$metainsert .= '--url= ';
$metainsert .= '--skip-themes --skip-plugins';
$meta_inserts[] = $metainsert;

Important: All the other multiple fields are going in as __1, __2 and so on. So I’m never actually stomping on the original meta_field name. But in the case of images, it’s one meta_value representing the gallery. If I add a new meta_key meta_value pair for the gallery it goes in at the end. But WordPress only looks for the first one! The meta_value isn’t the comma-separated list, but a filename. So I’ve re-named the image fields from “church_building_xxxxxx_pictures” to “church_building_xxxxxxx_images.”

Notice how I’m clearing the arrays and variables each time. For some reason even redeclaring $image_meta_array=array() wasn’t enough. I found that every single post had the same image. So that array had to be unset. Also, any of the strings would carry over persistently.

The $imagelink variable is usually something as simple as a filename. For example, one church’s exterior pictures array looks like this:

            [church_building_exterior_pictures] => Array
                    [0] => asf02.jpg
                    [1] => asf01.jpg
                    [2] => asf03.jpg
                    [3] => asf04.jpg
                    [4] => bloomstfrancis25.jpg

It may be more complicated than that, having a full path or something. But at long as it ends with that filename we should be good.

So the ‘wp db query “SELECT ID…’ query just grabs a post ID (just one, there might be duplicates but at this point I need to plunge ahead) and adds it to a simple array. Then we implode the array into the comma-separated list, and build a post meta add command. Because this is a gallery field, incrementing isn’t necessary. Which is a good thing because one of these has more than 80 images!

All Your Meta Inserts In One Place

This last chunk of code:

$uniqueMetas = array_unique($meta_inserts);
$metaoutput = fopen('/tmp/churchesmeta.txt','w');
foreach ( $uniqueMetas as $uniqueMeta ) {
fwrite($metaoutput, $uniqueMeta . "\n");

Takes the list of meta commands that has been generated, and de-dupes them. Then it puts them in sort order so all the meta commands for post xyz come out together, and prints them out to a temp file. I’ll use this for testing.

Echoing out these commands, and various other sanity checks along the way, helped me find a lot of errors. A few misspellings, the image arrays weren’t resetting properly, plus in one instance I’d mis-counted the number of potential interior designers. The index was missing for __5 and __6 in the duplicate fields array. I added those to the ACF group field, saved the group, looked up the new values, and ran the script again.

Trial by Fire

Now I have a file — 542K of add meta commands, to work through. But first I need to test a batch of them before I do a big run. I’m going to try it with post #1055. Here’s what it looks like on the dashboard (left), and the front end (right).

Next I’ll run the commands related to post #1055, in order. This is what they look like:

wp post meta add 1055 _church_building_architectural_style field_5f0f3ca3ede62 --url= --skip-themes --skip-plugins
wp post meta add 1055 _church_building_architectural_style__1 field_5f0f3cb5ede63 --url= --skip-themes --skip-plugins
wp post meta add 1055 _church_building_architectural_style__2 field_5f0f3cc3ede64 --url= --skip-themes --skip-plugins
wp post meta add 1055 _church_building_current_status field_5f0f4135f8ad6 --url= --skip-themes --skip-plugins
wp post meta add 1055 _church_building_exterior_images field_5f0f41d8f8ad9 --url= --skip-themes --skip-plugins
wp post meta add 1055 _church_building_fabricator_of_windows field_5f0f3d2e3ca0c --url= --skip-themes --skip-plugins
wp post meta add 1055 _church_building_fabricator_of_windows__1 field_5f0f3d2e3ca0d --url= --skip-themes --skip-plugins
wp post meta add 1055 _church_building_interior_images field_5f0f41b0f8ad8 --url= --skip-themes --skip-plugins
wp post meta add 1055 _church_building_renovations field_5f0f4002f8acb --url= --skip-themes --skip-plugins
wp post meta add 1055 _church_building_renovations__1 field_5f0f4002f8acc --url= --skip-themes --skip-plugins
wp post meta add 1055 _church_building_specific_notable_works_of_art field_5f0f3f3b8abf6 --url= --skip-themes --skip-plugins
wp post meta add 1055 _church_building_specific_notable_works_of_art__1 field_5f0f3f3b8abf7 --url= --skip-themes --skip-plugins
wp post meta add 1055 _church_building_year_opened field_5f0f4201f8adb --url= --skip-themes --skip-plugins
wp post meta add 1055 _date_of_establishment field_5f0e0c45c4340 --url= --skip-themes --skip-plugins
wp post meta add 1055 _ethnicity field_5f0e0c8ec4342 --url= --skip-themes --skip-plugins
wp post meta add 1055 _founding_pastor field_5f0e0c58c4341 --url= --skip-themes --skip-plugins
wp post meta add 1055 _name_of_parish field_5f0e0c34c433f --url= --skip-themes --skip-plugins
wp post meta add 1055 church_building_architectural_style__1 '"Renaissance Revival"' --url= --skip-themes --skip-plugins --format=json
wp post meta add 1055 church_building_architectural_style__2 '"Baroque Revival"' --url= --skip-themes --skip-plugins --format=json
wp post meta add 1055 church_building_exterior_images '3019,3020' --url= --skip-themes --skip-plugins
wp post meta add 1055 church_building_fabricator_of_windows__1 '"Ludwig von Gerichten"' --url= --skip-themes --skip-plugins --format=json
wp post meta add 1055 church_building_interior_images '3023,3025,3024,3021,3026,3022' --url= --skip-themes --skip-plugins
wp post meta add 1055 church_building_renovations__1 '"1925 - Interior decorated\r\n1936 - After fire, new ceiling, church repainted\r\n1995 - Fire - five windows destroyed; church restored"' --url= --skip-themes --skip-plugins --format=json
wp post meta add 1055 church_building_specific_notable_works_of_art__1 '"1919 - Windows by Ludwig von Gerichten, whose studio was in Ohio. The windows were made in Munich.\r\n1936 - Interior paintings by Stanislaus Mieszczanski"' --url= --skip-themes --skip-plugins --format=json

Each of these ran without incident. Now let’s see what our dashboard and front-end displays look like:

So at this point, it’s time to run the whole script and apply the commands as we go. A simple matter of copying a bunch of lines from the saved file in /tmp and pasting them into the command line. That way I’m sure to go at a manageable pace, and I can watch for errors in real time.

Then I’ll clean up the template and then — and then it’s done!


In this series I took two different Magic Fields implementations and developed ways to automate the translation to Advanced Custom Fields. In the site I used a child theme with custom post types, because there were several different post types to work with. In the Newark Churches site I used a child theme and just modified the main body, because everything on the site is the same.

Please comment if you have any questions, and thanks for reading!

    Leave a Reply

    Your email address will not be published. Required fields are marked *

    Share This