Is it possible to save Custom Field checkboxes as one array instead of separate wp_postmeta rows?

I’m using Gravity Forms with Advanced Custom Fields, mapping Post fields in my form to ACF.

I’ve run into a problem when the Custom Field in the GF form is checkboxes. ACF only recognizes the first checked box. I know exactly why: ACF wants checkboxes to be a serialized array in one wp_postmeta record, but GF saves each checkbox string as a separate record (each with the same meta_key).

I found the exact spot in GF where this save is happening: it’s lines 4651-4662 in forms_model.php. I was even able to get GF to save the data the way ACF wants it, with just a couple of modifications to this code.

But, of course, modifying code directly in the plugin is not a viable option. There are no hooks here to allow me to modify the output, nor does GF offer any options to change how it handles Custom Field checkboxes.

I’m sure there’s some reason why GF saves checkboxes this way, but it really doesn’t make any sense to me. Is there a way around this problem? I’m considering writing some code in my own plugin that uses the updated_postmeta hook to convert this, but it would be cleaner if there was a way to have it saved directly as an array in the first place.

Update: I did find a way to use an ACF hook to modify how ACF loads the value. This does seem to work, even when you go into the post and modify the ACF values directly later. One issue I haven’t yet resolved — although it isn’t apparently causing any problems — is that the multiple wp_postmeta records still exist, with each of them getting an identical serialized array value after saving.

Here’s the code:

add_filter('acf/load_value/type=checkbox', function($value, $post_id, $field) {
// Value should be an array, not a string
if (is_string($value)) {
$value = get_post_meta($post_id, $field['name'], false);
return $value;
}, 10, 3);

1 Like

It sounds like you have resolved it, but you can also use the gform_save_field_value filter to modify the data before it is saved in the database:

1 Like

Thanks… I wasn’t aware of this filter. (So many filters.) In principle I like the idea of doing the processing before the data gets saved, rather than manipulating it after the fact like I’m doing. I just wonder if there’s a good reason why GF saves checkbox data the way it does (again… seems kind of illogical to me). Maybe it’s a bit safer to take the approach I’m taking since I’m only manipulating it in cases where I know I want to manipulate it, vs. potentially breaking functionality in an add-on that expects the data in the standard GF format.