This was asked many times and the default answer “impossible” is right most of the times. But I have a special constellation that works with a little tweak:
What I wanted to do
I have products and suppliers. One product can have many suppliers, one supplier can offer many products.
Adding a supplier to a product should be accompanied by a note, e. g. “This is the cheapest supplier for this product, but they ship only on Fridays”.
Means two steps:
- A bidirectional relation
- A repeater-field for the relation and the note
It is near impossible to edit the relation from both sides. Adding a new related product to a supplier would have to create a new row in the repeater field, select the product as relation and … we do not care. Fortunately we only want to add related suppliers (including notes) and not vice versa.
So the final solution would be:
- Add or edit a relation to suppliers in products, optionally add a note for this relation
- Output in products: Company | Note
- Output in supplier: Product.
- Yep, no possibility to edit the relation from the supplier side, we want that
What I did
I tried a couple of things:
- https://www.advancedcustomfields.com/resources/bidirectional-relationships/ – This solution works with just a few lines in functions.php. Field values are hardcoded, but for a simple relation it is working fine. Unfortunately not working with a repeater.
- https://github.com/Hube2/acf-post2post/blob/master/acf-post2post.php – This solution works without any coding, just by identical field names. But inside a repeater … nope.
- https://github.com/Hube2/acf-filters-and-functions/blob/master/acf-reciprocal-relationship.php – This solution must be coded in functions.php but works like the post2post Plugin by using the same field name. You can also hardcode … but inside a repeater, you guessed it, nope.
- https://www.acf-extended.com/ or https://github.com/acf-extended/ACF-Extended – This plugin seems to be a multitool for ACF. It is soooo easy to set bi-directional relationships. After about 2 mins. everything worked out of the box, except … repeater fields.
What finally worked
Creating a bidirectional relationship with ACF Pro is pretty easy using one of the four solutions above. You only need to have a field on the toplevel (means not inside a repeater or similar). That means the easiest and most stable way is
- Create your two relationship fields and make them bidirectional using one of the four solutions
- Create your repeater with an relationship field inside (Post Object works best)
- Add the following code to your functions.php, change the three variables to fit your fields:
This function updates the relationship-field from the single post objects in my repeater. For me the repeater fields are the single source of truth. That means:
- If you delete all rows in the repeater, the contents of the relationship field will be deleted.
- If you add or delete row in the repeater, the contents of the relationship-field will be written as whole new value instead of appending new rows to the existing values.
- You should now hide the two relationship fields from edit to not confuse editors.
Have a look
And what about performance?
With a few hundred suppliers and a few thousand products in my platform I will not run into performance problems. If you have to cope with the same task but with a lot more post objects, you may consider using https://hookturn.io/downloads/acf-custom-database-tables/. I’m glad my solution worked without another premium plugin, but that would have been my next attempt.
Have some other idea for relationships, repeater fields and stuff like this? Leave a comment …