Support

Account

Home Forums Feature Requests New get_field functions or changes to existing

Helping

New get_field functions or changes to existing

  • I just spent two days trying to accomplish what should be a simple task. I’m posting here to get input on any better ways to accomplish it, and to put in an official feature request to solve the problem once-and-for-all.

    Feature Request:
    Change existing get_field(s) and get_field_object(s) to include a str(‘type’) and a bool(‘hierarchical’) option. Examples:

    
    get_field( $selector, [$post_id], [$format_value], [$type = false], [$hierarchical = true] );
    get_fields( [$post_id], [$format_value], [$type = false], [$hierarchical = true] );
    get_field_object( $selector, [$post_id = false], [$format_value = true], [$load_value = true], [$type = false], [$hierarchical = true] );
    get_field_objects( [$post_id = false], [$format_value = true], [$load_value = true], [$type = false], [$hierarchical = true] );
    
    1. Default for ‘type’ = false, and returns all field types.
    2. If is a single string value, only returns fields for that specific field type.
    3. If is an array of strings, only returns the field types specified in the array.
    1. Default for hierarchical = true, and that returns the current ACF array structure with nested arrays for child fields.
    2. If set to false, it returns a single-level array instead of nesting child arrays within the parent array.

    To give a visual example. Here’s a sample field group layout with multi-level parent/child fields, field types of ‘group’ and ‘Typography’:

    
    field-group
      test_typography_field
      heading_style_typography_field
      paragraph_style_typography_field
      single-level subfield group 
        test_subfield_typography_field
      multi-level subfield group
        level-1 group
          level-2 group
            multi_level_subfield_typograghy_field
    

    I wanted to be able to use the get_field(s) and get_field_object(s) functions to return a single-level array for only a specific field type with output like this:

    
    Array
    (
        [test_typography] => Array
            (
                [font_size] => 15
                [font_family] => Arial, Helvetica, sans-serif
                [font_weight] => 400
                [font_style] => normal
                [font_variant] => normal
                [font_stretch] => normal
                [line_height] => 
                [letter_spacing] => 0
                [text_align] => left
                [text_color] => #000
                [text_decoration] => none
                [text_transform] => none
            )
    
        [heading_style_typography] => Array
            (
                [font_size] => 15
                [font_family] => Arial, Helvetica, sans-serif
                [font_weight] => 400
                [font_style] => normal
                [font_variant] => normal
                [font_stretch] => normal
                [line_height] => 
                [letter_spacing] => 0
                [text_align] => left
                [text_color] => #000
                [text_decoration] => none
                [text_transform] => none
            )
    
        [paragraph_style_typography] => Array
            (
                [font_size] => 15
                [font_family] => "Times New Roman", Times,serif
                [font_weight] => 400
                [font_style] => normal
                [font_variant] => normal
                [font_stretch] => normal
                [line_height] => 
                [letter_spacing] => 0
                [text_align] => left
                [text_color] => #000
                [text_decoration] => none
                [text_transform] => none
            )
    
        [test_subfield_typography] => Array
            (
                [font_size] => 15
                [font_family] => Arial, Helvetica, sans-serif
                [font_weight] => 400
                [font_style] => normal
                [font_variant] => normal
                [font_stretch] => normal
                [line_height] => 
                [letter_spacing] => 0
                [text_align] => left
                [text_color] => #000
                [text_decoration] => none
                [text_transform] => none
            )
    
        [multi_level_subfield_typograghy_field] => Array
            (
                [font_size] => 15
                [font_family] => Arial, Helvetica, sans-serif
                [font_weight] => 400
                [font_style] => normal
                [font_variant] => normal
                [font_stretch] => normal
                [line_height] => 
                [letter_spacing] => 0
                [text_align] => left
                [text_color] => #000
                [text_decoration] => none
                [text_transform] => none
            )
    
    )
    

    It could easily be accomplished by modifying the get_field(s) and get_field_object(s) functions like I’m suggesting. The above output from a multi-level, multi-field_type field-group could be accomplished by simply:
    get_fields( $post_id, true, "Typography", false );

    Instead, read below for additional details, and my many failed attempts to accomplish this task, which I originally thought was going to be pretty straightforward.

    Details / Purpose:

    I’m making a development site specifically for testing out plugin development on the ACF Typography plugin (official – https://github.com/mujahidi/acf-typography, experimental – https://github.com/codejp3/acf-typography, wp directory – https://wordpress.org/plugins/advanced-custom-fields/).

    I have hooks going in all sort of places that display nitty-gritty details about ACF and ACF Typography data all through the dev site. One thing I needed to accomplish was to display details for EVERY Typography field present and in play on every page load that they’re attached to.

    Problem With Current ACF arrays returned:

    Presently, ACF is kinda intended for in-template display with the current data returned with get_field(s), get_field_object(s), get_sub_field, get_sub_field_object, and the have_rows/the_row API functions. The way those work requires you to know the field names you’re working with, and to know the layers where those field names are present.

    For testing the Typography plugin, it’s random fields per object. They could be parent fields, 1 level-deep child fields, or multi-level deep child fields. There’s no exact way to know per test object and per test entry for each test object type. The names of the fields are also unknown. It’s random generation for testing purposes. The child elements are unknown. It could be 10 layers deep, or 100 for that matter. Using the current approach of the (if has_rows, while has_rows, the_row) loop just isn’t realistic when you’re more than a few layers deep, and don’t even know what’s at each layer (random generated fields/relationships).

    The need was to get EVERY ‘Typography’ field for a test object into a standardized single-level array, regardless of parent/child relationship or field name. I could not accomplish this with the current ACF functions for getting field values.

    Failed Attempt 1:

    I originally tried 2 functions that both used the (if has_rows, while has_rows, the_row) loop, and would bounce between the two pulling out typography fields and adding to an array until it was the final level in the parent/child structure and only then would they return the final values array, but that was not accurate and required lots of additional checks for value types being passed between the two functions.

    Failed Attempt 2:

    Then I tried just getting the end() of each array from get_field_objects, but that would miss typography fields that weren’t exclusively parent-level or final-level, and the checks within looping arrays for ‘if it has subfields’ and ‘foreach subfield’ is just unrealistic and unmanageable.

    Successful Attempt 1:

    Then I tried just getting all the field names/types with get_field_objects, creating an array of only field names where the field type is ‘Typography’ and then just using the default wp get_post_meta to get the values for that field without the ACF parent-child structure as part of the returned array. This worked, but I didn’t like the approach due to the extra query per field just to get values that were already in the initial get_field_objects.

    Successful Attempt 2:

    I finally settled on this approach. Get all fields for current object with get_field_objects, and then array_walk_recursive through it to build out the exact array of field_name => [key => value] that I was trying to get. Here’s the working code for anyone trying to do something similar (until ACF releases new functions or changes existing ones like I’ve requested in this topic):

    
    // get all fields and field data
    $fields = get_field_objects($post_id);
    
    // if we got fields to work with
    if ($fields) {
    	
    	$subfieldsArray = array();
    	$name = false;
    	$type = false;
    	
    	array_walk_recursive( $fields, function( $value, $key ) use( &$subfieldsArray, &$name, &$type ){
    
    		// set name for current item
    		// for some reason font size keeps sneaking in when it's the value not the key
    		if ( $key == 'name' && !$value == 'font_size' ) {
    			
    			$name = $value;
    			
    		}
    		
    		// get and set field type for current item
    		if ( $key == 'type' && $name ) {
    			
    			$type = $value;
    			
    			// if it's the field type we're looking for, add it to the array
    			if ( $type == 'Typography' ) {
    				
    				$subfieldsArray[$name] = array();
    				
    			}						
    		}
    		
    		// if the current itme type has been added to the array,
    		// let's add the specifi values we're looking for to the array
    		if (isset($subfieldsArray[$name])) {
    			
    			if ( $key == 'font_size' ||
    				$key == 'font_family' ||
    				$key == 'font_weight' ||
    				$key == 'font_style' ||
    				$key == 'font_variant' ||
    				$key == 'font_stretch' ||
    				$key == 'line_height' ||
    				$key == 'letter_spacing' ||
    				$key == 'text_align' ||
    				$key == 'text_color' ||
    				$key == 'text_decoration' ||
    				$key == 'text_transform'
    			   ) {
    				
    				// for some reason font size keeps sneaking in when it's the value not the key
    				if ( !$key == 0 || !$value == 'font_size' ) {
    					
    					$subfieldsArray[$name][$key] = $value;
    					
    				}
    				
    			}
    			
    		}
    		
    	});
    
    	echo '<pre>';
    	echo print_r( $subfieldsArray );
    	echo '</pre>';
    	
    	// prints out the intended single-level array of field_name => [key => value] as shown at the top of this topic.
    
    }
    

    Conclusion:
    I have working code to accomplish the task of producing a single-level array for only a specific field type so there’s no big rush to try to make this happen, but I can’t imagine that I’m the only one looking for this functionality as part of ACF core. I can image a TON of uses for being able to specify field_type. I can also see how much easier it would be to work with subfield values if I could specify hierarchical=false so that the returned array didn’t have nested arrays of nested arrays of nested arrays of nested arrays when dealing with multi-level parent-child relationships. I hope this all makes sense to the ACF team. Thanks for your hard work!

    Suggestions:
    I welcome any suggestions for better/easier ways to accomplish this task.

  • You need to submit the feature requests directly to the developers. They do not actually monitor these forums on a regular basis.

Viewing 2 posts - 1 through 2 (of 2 total)

You must be logged in to reply to this topic.