Support

Account

Home Forums Add-ons Repeater Field Update sub field before/after save post

Solved

Update sub field before/after save post

  • Expected behavior:

    When user updates an ACF in the WP dashboard and hits UPDATE, code will check for updated Status field and if values have changed, will also modify Last Updated field, then save all information.

    Reality:

    The overall content is updated but the Last Updated field is not affected by the update_sub_field code. However, if I remove the return $post line at the end, the Last Updated field is saved, but the overall content reverts back to the original values (not saved).

    I need both to be saved! I have a feeling that things are just not happening in the right order and I can accomplish this if I can just figure out the proper filter/action to run, but so far none of these have worked with the below code (have tried different priorities as args, as well):

    add_action( 'acf/save_post' , 'update_post');
    add_action( 'save_post' , 'update_post');
    add_filter( 'wp_insert_post_data' , 'update_post');

    Any help is greatly appreciated. Thank you!

    function update_post( $post ) {
    
        $projectCount = -1;
    	
    	if( have_rows('project') ):
    
    		while( have_rows('project') ): the_row();
    
    			$taskCount = -1;
    			$projectCount++;
    
    			if( have_rows('project_issue') ):
    
    				while( have_rows('project_issue') ): the_row();
    
    					$taskCount++;
    
    					$oldValue 	= get_sub_field('project_current_status');
    					
    					$newValue 	= $_POST['acf']['field_594afbf65e909'][$projectCount]['field_594afd675e90d'][$taskCount]['field_594c05c666a9f'];
    
    					$date = date('Ymd');
    
    					$updated = ($oldValue !== $newValue) ? 'true' : 'false';
    
    					if ( $updated == 'true' ) { 
    						
    						update_sub_field('project_last_update', $date);
    								
    					}
    	
    				endwhile;
    
    			endif;
    
    		endwhile;
    
    	endif;
    
    	return $post;
    }
  • In case anyone ever reads this, solved with:

    add_action( 'update_post_meta', 'update_post', 10, 4 );

    …and removing the return at the end.

  • Perhaps someone can tell me why this code:

    $oldValue = get_sub_field('project_current_status');

    …is returning the last of all of the ‘project_current_status’ fields (total)!

    My understanding is that it should only be returning the field referenced inside of the ‘have_rows’ loop.

    Is this not correct? Thank you.

  • Looking back over your comment, to be honest I’m not sure where the problem is. However, if I was going to update a field associated with ACF and I needed to look at old values vs new values

    
    add_action('acf/save_post', 'update_post', 1);
    

    Setting the priority of 1 means that your function will run before ACF saves the new values. This means that you can use the ACF functions have_rows() and get_sub_field() to get the old values and $_POST['acf'] for the new values.

    In your OP you indicated that you tried this

    
    add_action( 'acf/save_post' , 'update_post');
    

    This sets the priority to 10, which is the same as when ACF runs it’s save. There isn’t any way to guarantee under this condition which will run first, your function or ACF.

    Looking at your last comment, you need to supply the post ID for the initial have_rows() calls in your filter so that ACF knows what post to look at.

    
    function update_post( $post_id ) {
    
        $projectCount = -1;
    	
    	if( have_rows('project', $post_id) ):
    
    		while( have_rows('project', $post_id) ): the_row();
    
    // after this you don't need to add $post_id for any sub fields
    

    Hope that helps

  • This is immensely helpful, thank you so much for lending a hand. =)

  • I had a very similar problem. I needed to compare both the previous and newly submitted value (of type array), whilst also updating the post after AFC made its changes. The goal was to create a computed/ calculated/ lookup/ rollup field for backlinking/ bidirectional linking purposes

    Here’s the code to achieve this.

    Note that you need two actions, the first one runs before the post is saved and stores the old data in a global variable.

    The second action than get the newly submitted form data and updates the desired fields. In below code the old and new values are compared and the update is only executed if the new value is different.

    
    
    // Global variable to store the old_field_value before the post is updated
    global $old_field_value;
    
    // Use the acf/validate_save_post action to get the old_field_value before the post is updated
    add_action('acf/validate_save_post', 'store_old_field_value', 10);
    
    function store_old_field_value() {
        global $old_field_value;
        $post_id = $_POST['post_ID'];
    
        if (get_post_type($post_id) === 'your_post_type') {
            $old_field_value = get_post_meta($post_id, 'your_field_name', true);
        }
    }
    
    // Automatically save related posts based on the linked posts and their associated posts
    add_action('acf/save_post', 'update_related_posts', 20);
    
    function update_related_posts($post_id) {
        global $old_field_value;
    
        // Check if the save is an auto-save, in which case we don't want to run this function
        if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) {
            return;
        }
    
        // Check if the current user has permission to edit the post
        if (!current_user_can('edit_post', $post_id)) {
            return;
        }
    
        // Check if the saved post is of the desired post type
        if (get_post_type($post_id) !== 'your_post_type') {
            return;
        }
    
        // Get submitted values.
        $new_values = $_POST['acf'];
    
        // Important add your 'your_field_key' (starting with "field_"), not the 'your_field_name'
        $new_field_value = is_array($new_values['your_field_key']) ? $new_values['your_field_key'] : array();
    
        // Check if the field has changed
        if ($old_field_value != $new_field_value) {
    
            // Initialize the $related_posts array
            $related_posts = array();
    
            // Iterate through the new linked posts and get the associated posts field value
            foreach ($new_field_value as $linked_post_id) {
                // Get the associated posts field value from the linked post using ACF's get_field() function
                $associated_posts = get_field('associated_posts_field_name', $linked_post_id);
    
                // Merge the associated posts with the main $related_posts array
                $related_posts = array_merge($related_posts, $associated_posts);
            }
    
            // Get the existing related posts field value from the current post using ACF's get_field() function
            $existing_related_posts = get_field('related_posts_field_name', $post_id);
            $existing_related_posts_arr = is_array($existing_related_posts) ? $existing_related_posts : array();
    
            // Merge the existing related posts with the new related posts array
            $related_posts = array_merge($related_posts, $existing_related_posts_arr);
    
            // Remove duplicate post IDs
            $related_posts = array_unique($related_posts);
    
            // Update the related posts field in the current post using ACF's update_field() function
            update_field('related_posts_field_name', $related_posts, $post_id);
        }
    }
    
    
Viewing 6 posts - 1 through 6 (of 6 total)

The topic ‘Update sub field before/after save post’ is closed to new replies.