ACF Relationships in Custom Post Type Permalink

The following you could add as a plugin or into your themes functions.php file. What we need to do is add a rewrite tag, custom query var, and finally replace the rewrite tag with the related post slug. Some things may vary from my code to yours. I assume chapters is the post type slug and that the relational field is returning an ID instead of an object, you may need to change these things based on your setup.

One thing you’ll need to do is when you’re creating your chapters post type, you’ll need to add in the placeholder on the rewrite slug:

/**
 * Create Rewrite Tag
 * We'll be able to hook in and replace this placeholder
 * 
 * @return void
 */
function wpse285382_chapters_setup() {

    // Add rewrite tag
    add_rewrite_tag(
        '%manga%',  // Placeholder
        '([^&]+)',  // Regex
        'manga="    // Expected query var
    );

    // Assign rewrite tag in post registation
    register_post_type( "chapters', array(
        /* ... */
        'rewrite' => array( 'slug' => 'mangas/%manga%', 'with_front' => false ),
        /* ... */
    ) );

}
add_action( 'init', 'wpse285382_chapters_setup' );


/**
 * Replace the placeholder rewrite tag with expected manga
 * 
 * @param String $post_link
 * @param WP_Post $post
 * 
 * @return String $post_link
 */
function wpse285382_chapter_link_replacements( $post_link, $post ) {

    // No Post ID? Drop out
    if( empty( $post ) ) {
        return $post_link;
    }

    // Make sure our post type is correct
    if( empty( $post ) || 'chapters' !== $post->post_type ) {
        return $post_link;
    }

    // Get related manga field
    $manga = get_field( 'related_manga', $post->ID );

    if( ! empty( $manga ) ) {

        // Grab Post Slug
        $manga_slug = get_post_field( 'post_name', $manga );

        // Replace rewrite tag in the given URL
        $post_link = str_replace( '%manga%', $manga_slug, $post_link );

    }

    return $post_link;

}
add_filter( 'post_type_link', 'wpse285382_chapter_link_replacements', 9, 2 );

This last bit should redirect any mismatched posts. We make sure that we have a slug to work with, we have a related post ID assigned, and the given slug and related post slug are the same, if they’re not we redirect them back to the archive page ( or where-ever you need to point them to ).

/**
 * Redirect mismatched related posts
 * 
 * @return void
 */
function wpse285382_chapter_redirects() {

    global $post, $wp_query;

    if( ! is_singular( 'chapterss' ) ) {
        return;
    }

    $redirect_to    = get_post_type_archive_link( 'chapters' );
    $given_slug     = $wp_query->get( 'manga' );
    $expected_manga = get_field( 'related_manga', $post->ID );

    if( empty( $given_slug ) || empty( $expected_manga ) ) {
        wp_redirect( $redirect_to );
        exit();
    }

    $expected_slug = get_post_field( 'post_name', $expected_manga );

    if( $given_slug !== $expected_slug ) {
        wp_redirect( $redirect_to );
        exit();
    }

}
add_action( 'template_redirect', 'wpse285382_chapter_redirects' );

Leave a Comment