Home › Forums › Add-ons › Repeater Field › BiDirectional Repeaters
Hello All,
Building a bidirectional Repeater Field has been something that I’ve been wanting to figure out for a while now, so here is what I have. The thought on this would be while saving a post, a specific repeater field, or when any repeater is updated through the various hooks this will run, with the example below being for a post being saved. I am posting this in hopes of other point out any issues or improvements to the idea. I don’t know how to build a plugin, but if it’s possible with this, please feel free to build it up if you’d like to. This is currently working in a couple scenarios for me, but am curious to see what others think. The only part I think could be an issue is the Select, but as long as you declared $wpdb as a global it works.
Setup: There are 2 custom post types called people and departments, and a repeater in each field group called people_departments and department_people respectively.
Each repeater then has a Post Object called select which is pointed to CPT departments for the people and pointed to CPT people for the departments.
Then the rest of the repeater will be various fields, like a text field called title (the persons department title), or id. These additional fields will be different depending on the combination of the person and department.
In the hook you do:
`
//Auto add and update Title field:
function save_post_functions( $post_id )
global $wpdb;
$my_post = array();
$my_post[‘ID’] = $post_id;
//get the post type and do an if to determine if its a person or department
if ( get_post_type( ) == ‘people’) {
$people_departments = get_field(‘people_departments’);
if ($people_departments) {
foreach($people_departments as $pdepartments) {
//select to find out if this row exists on the other end, if not add it, if yes update it
$select_row = $wpdb->get_row(“SELECT count(post_id) as rowcount,meta_key FROM wp_postmeta WHERE post_id = ‘”.$pdepartments[‘select’].”‘ AND meta_key LIKE ‘departments_people_%’ AND meta_value = ‘”.$post_id.”‘”);
//explode the meta_key to get the row number
$row_number = explode(“_”,$count->meta_key);
//if row does not exist, add it
if ($select_row->rowcount==0) {
$new_row = array(‘select’ => $post_id, ‘title’ => $pdepartments[‘title’], ‘id’ => $pdepartments[‘id’]);
add_row(‘departments_people’,$new_row,$pdepartments[‘select’]);
} else {
$new_row = array(‘select’ => $post_id, ‘title’ => $pdepartments[‘title’], ‘id’ => $pdepartments[‘id’]);
//add 1 to the row number since rows start on 1 in ACF
update_row(‘department_people’, $row_number[2]+1, $new_row, $pdepartments[‘select’] );
}
}
}
}
Hey again,
Hoping this will eventually help someone else, so I am making an update as I have continued working on this.
While working on this, I have failed to find a way to run this using the update_value hook, and therefore currently can only be done when the post is saved. Also just to point out, the posted code is only one side of the script, to do it bidirectional, duplicate from determining the post type and reverse all the field name. I also realized it wouldn’t delete rows if they were removed. So…..
First we have our action for the save post function with a value great then 10 so it runs after the values have saved
add_action('acf/save_post', 'save_post_functions', 20);
Then our function
function save_post_functions( $post_id )
//get the post type and do an if to determine if its a person or department
if ( get_post_type( ) == ‘people’) {
//get the persons departments and run through them
$people_departments = get_field(‘people_departments’);
if ($people_departments) {
foreach($people_departments as $pdepartments) {
//make sure the select in the row has a value, if not we do nothing
if ($pdepartments['select']!='') {
//get the departments people
$department_people = get_field('department_people',$pdepartment['select']);
//see if the person exists in the department already
$key = array_search($post_id, array_column($department_people, 'select'));
//build the row to update/add
$new_row = array( 'select' => $post_id, 'title' => $pdepartments['title'], 'id' => $pdepartments['id']);
//if $key equals false we add the row, otherwise update it (with key+1 since ACF rows start at 1
if ($key === false) {
add_row('department_people',$new_row,$pdepartment['select']);
} else {
update_row('department_people',$key+1,$new_row,$pdepartment['select']);
}
}
//that parts done
//now we check to see what needs to be deleted.
//first we get all departments with this persons post_ID using the custom post_ids_from_meta function (below)
$departments_with_person = post_ids_from_meta('department_people_%_select', $post_id);
//go through each department and see if it still exists for this person
foreach($departments_with_person as $dwp) {
list($dwp_id,$row) = explode("|",$dwp);
$key2 = array_search($dwp_id, array_column($people_departments, 'select'));
//if the department does not exists on the person, delete the person from the department
if($key2 === false) {
delete_row('department_people',$row+1,$dwp_id);
}
}
}
}
}
//custom function to get all the departments for this person (or all the people for the department)
`function post_ids_from_meta($key, $value) {
global $wpdb;
if(!is_array($post_ids)) { $post_ids = array(); }
$metas = $wpdb->get_results(“SELECT post_id,meta_key FROM wp_postmeta WHERE meta_value = ‘”.$value.”‘ AND meta_key LIKE ‘”.$key.”%'”);
if($metas) {
foreach($metas as $meta) {
$row_number = explode(‘_’,$meta->meta_key);
array_push($post_ids,$meta->post_id.”|”.$row_number[2]);
}
}
return($post_ids);
}
You must be logged in to reply to this topic.
Welcome to the Advanced Custom Fields community forum.
Browse through ideas, snippets of code, questions and answers between fellow ACF users
Helping others is a great way to earn karma, gain badges and help ACF development!
🚨 The 2023 ACF Annual Survey closes tomorrow! This is your last chance to complete the survey and help guide the evolution of ACF. https://t.co/0cgr9ZFOJ5
— Advanced Custom Fields (@wp_acf) May 18, 2023
© 2023 Advanced Custom Fields.
We use cookies to offer you a better browsing experience, analyze site traffic and personalize content. Read about how we use cookies and how you can control them in our Cookie Policy. If you continue to use this site, you consent to our use of cookies.