wanted to let an admin attach an icon (dashicon or uploaded img) to each global
product attribute (e.g. pa_length, pa_paper-type), then show them as icon cards
on the single product page.
wasted a lot of time trying to do this w/ acf/scf field groups on the attribute term edit screen. everything failed for the same root cause:
- a synced scf field group lands in the db w/
location: []. that empty array short-circuitsacf_get_field_group_visibility()before any location filter runs. so no filter ever saves it. acf_add_local_field_group()in php fired too early. the file is required during theme setup, beforeinit, so the group isn't in scf's registry yet when it checks visibility.acf/load_field_groupinjections got wiped by_acf_apply_get_local_internal_posts(priority 20) merging the empty-location json back over them.acf/location/rule_match/taxonomyfilters never fired, again because of thelocation: []short-circuit above.
basically two layers of empty-location state (db record + json file) fighting each other.
the diagnostic that finally cut through it: temporarily set the field group location
to Taxonomy == product_cat & edit a category. it showed up. so scf does hook
taxonomy screens fine, the problem was specifically the dynamic pa_* wildcard, not
scf itself.
lesson: if you need a field on all pa_* taxonomies dynamically, acf/scf fights
you the whole way. also looked at native term meta ({$taxonomy}_edit_form_fields),
would've worked but it's the wrong granularity. the icon belongs to the
attribute, not each term value under it.
dropped acf entirely. woo already renders an add/edit form for each global attribute & fires hooks around it. so store the icon as a plain option keyed by taxonomy. no field groups, no sync step, no location rules, no json.
// render the picker on woo's attribute add/edit screens
add_action( 'woocommerce_after_edit_attribute_fields', /* render field from option */ );
add_action( 'woocommerce_after_add_attribute_fields', /* render empty field */ );
// persist on save
add_action( 'woocommerce_attribute_updated', function ( $id, $data, $old_slug ) {
$taxonomy = wc_attribute_taxonomy_name_by_id( $id );
// type in {'', 'dashicons', 'media'}, value = dashicon class or attachment id
update_option( 'wc_attr_icon_' . $taxonomy, $icon, false ); // delete_option if 'none'
}, 10, 3 );
add_action( 'woocommerce_attribute_added', /* same, via wc_attribute_taxonomy_name() */ );
// wp_enqueue_media() on admin so the img picker worksstorage shape:
wc_attr_icon_{taxonomy} => [ 'type' => 'dashicons'|'media', 'value' =>
'dashicons-info'|<attachment_id> ]
front end — pull the option per taxonomy attribute & build the card:
foreach ( $product->get_attributes() as $attribute ) {
if ( $attribute->is_taxonomy() ) {
$icon = get_option( 'wc_attr_icon_' . $attribute->get_name() ); // [] if none
}
// card: icon (dashicon span OR wp_get_attachment_image_url), label, value
}- the icon is a property of the attribute, not the term. an option keyed by taxonomy is the right model & it sidesteps both acf and term meta.
- woo's
woocommerce_after_{edit,add}_attribute_fields+woocommerce_attribute_{updated,added}hooks are the clean, supported way to extend the attribute admin. no plugin layer needed. - don't reach for acf/scf for dynamic-location fields. an empty
location: []on a synced group short-circuits visibility before any filter runs, & you'll chase it for hours