Index of /Andrej Ciho/Old Blog/WordPress/Referential Integrity with ACF’s post object relational field

Back Parent Directory 2014-05-15 12:18

I use the Advanced Custom Fields (ACF) just about any time I need to quickly add additional fields to a WordPress page (or a post of another post type). I’ve purchased and regularly use most of their available add-ons.

They have several relational field types, one of them being Post Object. In a nutshell, when you’re editing a post you can relate it to a specific page (or vice versa). You can filter by post type, taxonomy etc.

For an automotive website I’ve used this to relate engines to vehicle models and makes. For medical websites I’ve used this to relate medical services to practice locations. It is extremely powerful.

One weakness is that if you delete an object to which you related another you end up breaking the reference. For example: If I deleted “Toyota Camry” which is a post of the custom type “Vehicle Make” (on the automotive website I mentioned above) I would end up with broken references on all engines I related to “Toyota Camry” using the ACF’s post object field. To help prevent the administrator of that website from doing just that I whipped up the following function and hooked it to the “wp_trash_post” action hook:

function ac_restrict_post_deletion( $post_ID ) {
    global $wpdb;

	// This is the query you will edit based on what
	$related_objects = $wpdb->get_results( $wpdb->prepare(
				"SELECT p.ID, p.post_title
				 FROM $wpdb->posts p
				 INNER JOIN $wpdb->postmeta pm ON pm.post_id = p.ID
				 WHERE p.post_type = 'vehicle_engine'
				 AND p.post_status = 'publish'
				 AND pm.meta_key = 'vehicle_model'
				 AND pm.meta_value = %d
				", $post_ID ) );

	if ( count( $related_objects ) > 0 ) {
		$to_be_deleted_title = get_the_title( $post_ID );

        printf( '<p>Deleting <em> %s </em> would break the referential relationships that the following objects have to it. Please remove these relationship first or simply click the &quot;Back&quot; button in your browser to return to the previous screen.<p>', $to_be_deleted_title );
		print '<ul>';
		$site_url = site_url( '/wp-admin/', 'admin' );
		foreach ( $related_objects as $obj ) {
			printf( '<li>%s <a href="%spost.php?post=%d&amp;action=edit">[Edit]</a></li>', $obj->post_title, $site_url, $obj->ID );
		print '</ul>';
add_action( 'wp_trash_post', 'ac_restrict_post_deletion', 10, 1 );

It presents you the following screen:


Obviously if you’re going to use this you’ll need to modify the query populating $related_objects, specifically the post types and meta keys.

Leave a Comment
*Required (Never published)

This website is powered by WordPress, using the IndexOf theme.