4

After looking at documentation and searching around, I haven't been able to find anything, so here goes:

Are there any way of custom-post-type-inheritance, and an url structure like this:

domain.com/%parenttype%/%parentname%/%posttype/%postname%/

Lets say artists have songs, would look like:

domain.com/artist/john-lennon/songs/imagine/

I haven't seen this done in development before. Does anyone know anything about this?

2
  • It would be a process similar to using a taxonomy term in a permalink, like in this answer. The extra step you will need is a mechanism for selecting / saving the parent post ID to the child's post meta.
    – Milo
    Oct 8 '15 at 15:09
  • That's what I thought. I just wondered, if anyone had made that before. Oct 8 '15 at 15:21
1

Here we go:

  1. Register your two CPT (= custom post types) e.g. artist, song
  2. Edit the rewrite slug from your child CPT to parent-type/%parent-slug%/child-slug (Attention: Don't use the same word for parent-type and parent-slug; parent-slug should match your parent CPT slug)
  3. Add a meta box to your child CPT, where you can define a parent CPT
  4. Modify the child CPT permalink to your needs

I wrapped it all up, ready to use:

class myArtistSongs{

    function init_post_types() {
        $args = array(
            'menu_position' => 8,
            'labels' => array(
                'name' => __('Songs', 'myArtistSongs'),
                'all_items' => __('All Songs', 'myArtistSongs'),
                'singular_name' => __('Song', 'myArtistSongs')
            ),
            'menu_icon' => 'dashicons-format-audio',
            'public' => true,
            'publicly_queryable' => true,
            'query_var' => false,
            'capability_type' => 'post',
            'has_archive' => false,
            'rewrite' => array(
                'slug' => 'artist/%artist%/songs',
                'feeds' => true,
                'pages' => true,
                'with_front' => true,
            ),
            'taxonomies' => array(
                'artist'
            ),
            'supports' => array(
                'title',
                'editor',
                'thumbnail',
                'excerpt'
            )
        );
        register_post_type( 'song', $args);
        $args = array(
            'menu_position' => 8,
            'labels' => array(
                'name' => __('Artists', 'myArtistSongs'),
                'all_items' => __('All Artists', 'myArtistSongs'),
                'singular_name' => __('Artist', 'myArtistSongs')
            ),
            'menu_icon' => 'dashicons-groups',
            'public' => true,
            'publicly_queryable' => true,
            'query_var' => false,
            'capability_type' => 'post',
            'has_archive' => false,
            'rewrite' => array(
                'slug' => 'artists',
                'feeds' => true,
                'pages' => true,
                'with_front' => true,
            ),
            'taxonomies' => array(
                'artist'
            ),
            'supports' => array(
                'title',
                'editor',
                'thumbnail',
                'excerpt'
            )
        );
        register_post_type( 'artist', $args);
    }

    static function song_permalink($permalink, $post_id, $leavename) {
        if (strpos($permalink, '%artist%') === FALSE) return $permalink;
        $post = get_post($post_id);
        if (!$post) return $permalink;
        $artist = get_post_meta($post->ID, '_artist', true);
        if ($artist > 0) {
            $artist = get_post($artist);
            if (!$artist) $artist = false;
            else $artist = $artist->post_name;
        }
        if (!$artist) $artist = 'no-artist';
        return str_replace('%artist%', $artist, $permalink);
    }

    function add_meta_box() {
        add_meta_box(
            'article-parent',
            __('Artist',''),
            array('myArtistSongs', 'meta_box'),
            'song',
            'side',
            'low'
        );
    }

    function meta_box($post) {
        $artist = get_post_meta($post->ID, '_artist', true);
        global $wp_query, $post;
        $old_wp_query = $wp_query;
        $old_post = $post;
        $loop = new WP_Query(array('post_type' => 'artist', 'posts_per_page=-1'));
        echo "<select name='artist' id='artist'>";
        $no_value = __('(no artist)','myArtistSongs');
        echo "<option value=''".(empty($artist)?" selected='selected'":'').">".$no_value."</option>";
        if($loop->have_posts()) while ($loop->have_posts()) {
            $loop->the_post();
            $o_id = get_the_ID();
            $o = get_the_title();
            echo "<option value='{$o_id}'".(!empty($artist) && $artist == $o_id?" selected='selected'":'').">{$o}</option>";
        }
        echo "</select>";
        $post = $old_post;
        $wp_query = $old_wp_query;
    }

    function save($post_id) {
        if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE )
            return;
        if ( !current_user_can( 'edit_post', $post_id ) )
            return;
        if ($_POST['artist']) {
            update_post_meta($post_id, '_artist', $_POST['artist']);
        } else {
            delete_post_meta($post_id, '_artist');
        }
    }
}

add_action('init', array('myArtistSongs', 'init_post_types'));
add_filter('post_link',  array('myArtistSongs', 'song_permalink'), 10, 3);
add_filter('post_type_link',  array('myArtistSongs', 'song_permalink'), 10, 3);
add_action('add_meta_boxes', array('myArtistSongs', 'add_meta_box'));
add_action( 'save_post', array('myArtistSongs','save') );

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.