ACF 6.7+ Compatibility Layer

  • JNext lesson
  • KPrevious lesson
  • FSearch lessons
  • EscClear search

The Problem

ACF 6.7 changed how acf_setup_meta() processes flat block data stored in Gutenberg block comments. After this change, get_field() started returning false or empty values for fields inside block render templates. This broke any block that relied on get_field() to read ACF data during rendering.

ACF 6.7 changed how flat block meta is processed, and get_field() silently started returning empty values inside blocks. This compatibility layer is the fix: it detects the broken path and restores field access without touching your stored content. If your blocks went blank after an ACF update, this lesson is the explanation.

The issue affects multiple data formats because ACF blocks store field data differently depending on how the content was saved:

  • Native ACF formatget_field() returns structured arrays (works in older ACF versions).
  • Flat indexed format – Fields stored as repeater_0_subfield, repeater_1_subfield (created by REST API saves, e.g. from external tools or headless setups).
  • Nested row format – Fields stored as repeater.row-0.subfield (ACF 6.7+ block comment format).

The Solution

The compatibility layer in includes/compat.php provides three helper functions that transparently handle all data formats.

acf_blocks_get_field( $name, $block )

Drop-in replacement for get_field() in block templates. Tries get_field() first. If it returns false/null/empty, falls back to reading from $block['data'][$name].

acf_blocks_get_repeater( $name, $sub_names, $block )

Reads repeater fields from any of the three data formats. It:

  1. Tries get_field() for native ACF arrays.
  2. Falls back to parsing flat indexed keys (name_0_subfield, name_1_subfield).
  3. Falls back to parsing nested row format (name.row-0.subfield).

Row count is determined by either reading the $data[$name] count value or scanning for sequential keys.

acf_blocks_get_nested_repeater( $parent_key, $sub_names, $data )

Handles repeaters inside repeaters. Works the same as acf_blocks_get_repeater but takes a full flat key prefix (e.g. products_0_features) and operates on the raw $block['data'] array.

When flat keys are not found, it uses acf_blocks_resolve_nested_key() to navigate through the nested data structure, mapping numeric segments to row-N keys.

Editor Reconstruction Filter

The render_block_data filter (acf_blocks_reconstruct_nested_repeaters) runs on admin pages and REST API requests. It converts flat repeater keys back into the nested row-N format that ACF’s JavaScript expects.

This is necessary because content saved via the REST API uses flat keys, but the block editor needs nested objects to populate its fields correctly. Without this filter, editing a block saved via REST API would show empty fields in the editor.

The filter:

  1. Checks if the block is an ACF block (acf/ prefix).
  2. Finds all repeater fields with nested repeaters for that block (using acf_blocks_find_repeater_fields()).
  3. For each repeater with flat indexed data, rebuilds it into row-N nested format.

The repeater field detection works generically. It scans registered ACF field groups rather than hard-coding block names, so any new block with nested repeaters benefits automatically.

Key Resolution

The function acf_blocks_resolve_nested_key() is a recursive resolver that maps flat keys like products_0_features through nested data by trying progressively longer key segments (longest first). This handles field names that contain underscores without ambiguity.

For example, given the flat key my_field_0_sub_field and nested data, it tries:

  1. my_field_0_sub_field as a single key
  2. my_field_0_sub + field
  3. my_field_0 + sub_field / sub + field
  4. my_field + 0 (maps to row-0) + sub_field
  5. And so on…

This ensures correct resolution even when field names contain underscores.

Quick answers to common questions:

Why did my ACF blocks stop showing field data after updating ACF?

ACF 6.7 changed acf_setup_meta() processing for flat block data stored in block comments, breaking get_field() in that context. The plugin’s compatibility layer detects affected versions and restores the old behavior; updating ACF Blocks fixes it without content changes.

Is the compatibility layer safe to keep enabled?

Yes; it activates only on the ACF versions that need it and is a no-op elsewhere. It exists so your content renders identically across the ACF 6.6/6.7 boundary.