Support

Account

Home Forums ACF PRO Bidirectional Relationship, different field names, with get/update fields only

Solved

Bidirectional Relationship, different field names, with get/update fields only

  • Hello All,

    I have been reading around and have not been able to get this working, and am hoping someone, maybe John “the bidirectional King” Huebner.
    I have used the Bidirectional tutorial on here and also John’s bidirectional Relationship tutorial but neither are working the way I need them and I can’t figure out how to adjust to get it working. I currently have the ACF Custom Database Tables plugin installed on my site, which stores the custom fields created by ACF in custom tables, and this is causing the above scripts to not work.

    My setup is that I have Artists & Releases, and want them to be connected and bidirectional.
    The first script requires field names to be the same, but CDT requires the different fields on different post types to have different names. So I have artist_release and release_artist

    The second script pulls data using get_meta, but since the values are stored in custom database tables, it won’t pull the data using get_meta. I would have to use get_field and update_field, but have tried just updating the script to use those and when trying to update it either times out or runs forever.

    I then thought I could use the first script, and assign the second field name based on the first. So I added in the “if($field_name =” part, and then assigned the field_name2 and field_key2 and adjusted the get/update fields to use the second name/key, but this isn’t working either. Any help or suggestions would be greatly appreciated!

    function bidirectional_acf_update_value( $value, $post_id, $field  ) {
    	
    	// vars
    	$field_name = $field['name'];
    	$field_key = $field['key'];
    	
    	if($field_name = 'artist_releases') { $field_name2 = 'release_artists'; $field_key2 = 'field_5bf7a2e215e5c'; }
    	if($field_name = 'release_artists') { $field_name2 = 'artist_releases'; $field_key2 = 'field_5bf79ed45b371'; }
    		
    	$global_name = 'is_updating_' . $field_name;
    	
    	// bail early if this filter was triggered from the update_field() function called within the loop below
    	// - this prevents an inifinte loop
    	if( !empty($GLOBALS[ $global_name ]) ) return $value;
    	// set global variable to avoid inifite loop
    	// - could also remove_filter() then add_filter() again, but this is simpler
    	$GLOBALS[ $global_name ] = 1;
    
    	// loop over selected posts and add this $post_id
    	if( is_array($value) ) {
    		foreach( $value as $post_id2 ) {
    			
    			// load existing related posts
    			$value2 = get_field($field_name2, $post_id2, false);
    			// allow for selected posts to not contain a value
    			if( empty($value2) ) {
    				$value2 = array();
    			}
    			// bail early if the current $post_id is already found in selected post's $value2
    			if( in_array($post_id, $value2) ) continue;
    			// append the current $post_id to the selected post's 'related_posts' value
    			$value2[] = $post_id;
    			// update the selected post's value (use field's key for performance)
    			update_field($field_key2, $value2, $post_id2);
    		}
    	}
    	
    	
    	// find posts which have been removed
    	$old_value = get_field($field_name, $post_id, false);
    	if( is_array($old_value) ) {
    		foreach( $old_value as $post_id2 ) {
    			// bail early if this value has not been removed
    			if( is_array($value) && in_array($post_id2, $value) ) continue;
    			// load existing related posts
    			$value2 = get_field($field_name2, $post_id2, false);
    			// bail early if no value
    			if( empty($value2) ) continue;
    			// find the position of $post_id within $value2 so we can remove it
    			$pos = array_search($post_id, $value2);
    			// remove
    			unset( $value2[ $pos] );
    			// update the un-selected post's value (use field's key for performance)
    			update_field($field_key2, $value2, $post_id2);
    		}
    	}
    	// reset global varibale to allow this filter to function as per normal
    	$GLOBALS[ $global_name ] = 0;
    
    	// return
      return $value;
    }
    
    add_filter('acf/update_value/name=related_posts', 'bidirectional_acf_update_value', 10, 3);
  • Just wanted to post that I figured out my errors on this, and now have it working!
    First in the filter it should have been

    add_filter('acf/update_value/type=relationships', 'bidirectional_acf_update_value', 10, 3);
    not
    add_filter('acf/update_value/name=related_posts', 'bidirectional_acf_update_value', 10, 3);
    referencing the relationship field type

    The other issue was when assigning the second field_name and field_key I had a single =

    if($field_name = 'artist_releases') { $field_name2 = 'release_artists'; $field_key2 = 'field_5bf7a2e215e5c'; }
    	if($field_name = 'release_artists') { $field_name2 = 'artist_releases'; $field_key2 = 'field_5bf79ed45b371'; }

    should have been

    if($field_name == 'artist_releases') { $field_name2 = 'release_artists'; $field_key2 = 'field_5bf7a2e215e5c'; }
    	if($field_name == 'release_artists') { $field_name2 = 'artist_releases'; $field_key2 = 'field_5bf79ed45b371'; }

    This now works for bidirectional relationships with different names.
    Thanks!

  • Didn’t see this until now, glad you got it working.

    If you are talking about this example: https://github.com/Hube2/acf-filters-and-functions/blob/master/acf-reciprocal-relationship. Yes, I do have a tendency to use WP function, I’m not exactly sure why I did so in the example since ACF must be running to for the filter to work. The only thing that I can thing of was that I was thinking about if the fields are not set already which would cause update_field() using the field name to fail. I also wanted to get raw array values. This could all be rewritten using ACF field functions if the field key is uses for getting and updating and when getting values if you supply the 3rd parameter get_field('field_key', $post_id, false); I’ll look at doing this if I get some time and I remember.

  • Hey John,
    No worries. I posted and then solved it pretty quickly. Didn’t really give you a chance to see it.
    Yes, that is the example I was talking about. The above post I made is working great for my purposes, and I have added additional if($field_name statements to match up all my desired bidirectional relationships to eachother.
    I understand the idea if it isn’t already set, but so far all is working well. Fingers Crossed.

    Thanks!

  • I’m going to need to look at reworking my plugin to use acf functions. I did not take into account other plugins that may be dependent on acf function getting called. When I built the plugin I was more concerned with not having errors on the site.

  • For anyone stumbling across this very useful post with limited php knowledge:
    For me I had to use:

    add_filter('acf/update_value/type=relationship', 'bidirectional_acf_update_value', 10, 3);

    Instead of relationships, not 100% sure but I believe they changed the naming somewhere down the line.

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

The topic ‘Bidirectional Relationship, different field names, with get/update fields only’ is closed to new replies.