Support

Account

Home Forums General Issues Get_fields() returns false until I update the post

Solved

Get_fields() returns false until I update the post

  • Hi

    I’ve written an application in my theme that populates ACF fields for a custom post type using the update_field() function.

    When I log into WordPress I can see the ACF fields in my post are all populated, go through to the front end and get_fields() returns false. If I then go back into my post and hit ‘update’ and go back to the front end, and get_fields() returns the fields. It’s very strange!

    Any ideas, anyone?

  • Ignore me! I fixed it! I read on the API page that when creating the post programatically, I need to use $field_key instead of $field_name as the first param of update_field().

    I’ve written a little utility function for anyone else who wants to use the $field_name instead of $field_key when programatically adding a post and then a custom field value.

    The $params argument is the array used when calling register_field_group(), $field_name is obviously the field name.

    	
    // Function to get an ACF Key for a field based on the params used to create the fieldset
    	function acf_field_key($params = array(), $field_name) {
    		
    		if (empty($params) or !isset($params['fields'])) {
    			
    			return $field_name;
    		}
    		
    		// Loop and find the value
    		foreach ($params['fields'] as $field) {
    			
    			if ($field['name'] == $field_name) {
    				
    				return $field['key'];
    			}
    		}
    	}

    Usage:

    
    $field_key = acf_field_key($acf_init_args, $field_name);
    
    update_field($field_key, $value, $post_id);
    
  • Hi

    I happen to have the exact same issue as you. Your solution looks good but my question is where do you get that “$params” array from?

    Thanks!

  • yeah please could you give some more infos on your helper function?

    thank !

  • Thanks for the tip.

    The fact that you must use the Key rather than the name worked for me.

    didn’t use the helper function but didn’t need to in my case.

    Thanks again

  • I like the helper function here, but what if I am not registering the field groups?

    is there another similar function to get the key value of the field?

    I use wp_insert_post to import data into wordpress, should i use a different function. I have the same issue as you. get_fields() is empty until i manually save my post.

    I don’t want to run into this issue anymore. Let me know your suggestions.

    I may answered my own question here. I believe I can write a function where I pass it the name of the field and then use this get_field_objects to get the key. Thoughts?

  • Any ACF function using the field name will fail if there isn’t already a value in the DB for the field. ACF depends on the field key reference in the DB and this does not exist for that were never saved.

  • Thank you John.

    I found a helper function called acf_maybe_get_field() – my plan is to use this function to get the field keys of each field.

    I will use wp_insert_post to create the post.

    Then after successful post creation, I will use update_field with the field key to update the post field values. This should save the data into wordpress as if i had manually added it in the wp-admin.

    From what i have found acf_maybe_get_field() is the only function that can get me the field keys even before the values exist.

    Does this sound like a solid plan?

  • Actually, no.

    This function like all others requires that the field key reference exists in the database for the current $post_id. It uses a combination of the post ID and field name to look up the field key reference.

    It all ends with the function acf_get_metadata(). In this function you will find

    
    $meta = get_metadata( $type, $id, "{$prefix}{$name}", false );
    

    $prefix in this case in an underscore (_), so it is trying to get the meta value of the meta key (your field name) prefixed with “_”. This is where the field key reference is stored. This meta value will only be set if the post already has a value for the field.

    As stated in the update_field() document

    Updating via field key

    This example shows how to achieve the same result as above using the field’s key instead of its name. The field’s key should be used when saving a new value to a post (when no value exists). This helps ACF create the correct ‘reference’ between the value and the field’s settings.

    The reason this is it because field names can be duplicated. All ACF operations actually need the field key to work. Field keys are unique. When you save a new post in the admin every input name is the field key, not the field name. ACF really has no way of knowing what field you are referencing by a field name and the field name has no meaning without the reference, which is why a field key reference is inserted into the DB for every field value that is saved for every post.

  • @hube2 What function should I use to get the field key for this scenario? I can pass the field name and the post id to whatever function to get the field key. I am building a new custom importer, so i need a way to get the field key before any value has been stored into the field. I thought acf_maybe_get_field would be the ticket. It seems to work great.

    I have some data that suffers from not having the reference data in the database. However when i edit the post, i see all of the fields filled in on the edit post screen. I know the data is there, but the data was imported via field name not field key.

    I want to rectify this error in my new importer.

    This data was imported using a custom script. I did some experimentation. I had tried function get_fields(), get_field_object(), get_field_objects() – none of these worked to get field data. They all returned empty.

    I do not want to hard code the field keys into my importer because the field keys will change from environment to environment. I work in a 4 environment. local, test, staging, and prod. Just looking for a way to get the field keys programmatically. That’s why i was going to use acf_maybe_get_field to get the field key and then save the data using wp_insert_post and run a script that also update_fields using the field keys during the import process.

    What function should i use to get the field keys?

  • @hube2 This is what i was going to do…but are you saying don’t use acf_maybe_get_field()? With my broken data, it seems to work well. I can get the field_key by passing it the name of the field and the post id. I was going to do something simple like this.

    function helper_get_field_key($field_name, $post_id){
      $maybe_field_obj = acf_maybe_get_field( $field_name, $post_id, false );
    
      return $maybe_field_obj['key'];      
    }
    $get_field_key_email = helper_get_field_key('email', $post_id);
    print_r($get_field_key_email);

    Returns: field_5f401336ed966

    This output the field key for the email field that is in that post id.

    If there is a better way to get the field_key programmatically when no value exists yet, I’m all ears…Would love to have a function to use just to get the field key.

  • I just tested acf_maybe_get_field() on a field that exists but was never saved. The function returns false. I have no idea how you are getting the field key by using that function if the field has no value.

    Under these conditions this line should be causing a PHP Undefined Index Warning:

    
    return $maybe_field_obj['key'];
    

    There is no reliable way that I know of using just the field name to get a field key for a field that does not have a value for a specific post.

    You could potentially use acf_maybe_get_field() if you supplied a post ID for a post that you know will have the value set. From what I’m hearing there would be no way to know what post ID to use.

    You could possibly do a query to get a post where the field key references already exist. Let’s assume that you know that if the field “email” exists for a post and has a field key reference in the db that all other fields will also exist.

    
    $args = array(
      'post_type' => 'your-post_type',
      'posts_per_page' => 1,
      'no_found_rows' => true,
      'meta_query' => array(
        array(
          'key' => '_email'
          'compare' => 'EXISTS'
        }
      )
    );
    $test_query = new WP_Query($args);
    if (!empty($test_query->posts) {
      $valid_fields_post_id = $test_query->posts[0]->ID;
    }
    

    But this will not work unless you can be sure all of the field references exist. You could also check for the existence of all field key references but I think if you have too many fields you need to check that the query could time out.

  • BTW, I will have the post id because i am doing wp_insert_post which returns the newly created post.

    The data I am currently using for testing with acf_maybe_get_field is data that was already imported, but not imported using the field_key. It was just using the wp_insert_post and the field names. This data when I use get_fields() returns null.

    In my new importer, I’m going to do like the example shows on the link you provided. I need to test this, but i was thinking something like this:

    function helper_get_field_key($field_name, $post_id){
      $maybe_field_obj = acf_maybe_get_field( $field_name, $post_id, false );
    
      return $maybe_field_obj['key'];      
    }
    
    // Create new post.
    $post_data = array(
        'post_title'    => 'My post',
        'post_type'     => 'my-post-type',
        'post_status'   => 'publish'
    );
    $post_id = wp_insert_post( $post_data );
    
    // Save a basic text value.
    $get_field_key_email = helper_get_field_key('email', $post_id);
    $value = "test@test.com";
    update_field( $get_field_key_email, $value, $post_id );

    I think something like this will work, i haven’t tested this exact scenario yet. I will today though and i can report back.

  • This does go to show that developers need a function to get the field keys.

    I propose something like: get_field_key( $field_group, $field_name ) ?

    This way you can just give it the field group id: group_123456789

    And the name of the field in the group.

    The function would return the field key. Noone wants to hard code the field keys into the code because when you create the fields in another environment, the field keys can change on you.

  • I am not an ACF developer. Just the guy that patrols these forums. The developers don’t monitor these forums. To submit a feature request you need to contact them directly.

    When I duplicate a field group on multiple sites I do this by either creating the field group in the theme in the acf-json folder or exporting and importing the field group, or even building common field groups into a plugin.

    When I do imports where I will not have this standardization then I use WP All Import Pro with the ACF add on that deals with updating the fields properly.

    I realize that it is too late for your current situation. But if you will have standardized fields on multiple sites then these should be done so that they are the same field names and keys. But I would look into a tool like WP all import that will do this rather than trying to roll your own.

  • @hube2 I am working in a very locked down system.

    Thank you for your help and suggestions. We did consider at some point putting all of the json for the fields groups in our theme, but because our site is already existing and we didn’t do that from the beginning we felt it to be too risky at this point.

    For this thing i am making, i will export the fields and import them into my other environments. I still want to be able to get the field_keys programmatically so i don’t have to hard code all of those values.

    Thanks!

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

You must be logged in to reply to this topic.