This is the code i have until now to add a CPT articles and taxonomy articles-category.

The code works, sort off. The pages are displaing correct (when i access them directly):

articles/

articles/categ-slug/

articles/categ-slug/post-slug/

The problem appears when the permalink are generated automatically (eg: yoast breadcrumbs)

<span typeof="v:Breadcrumb">
<a href="https://wordpress.stackexchange.com/questions/204681/example.com" rel="v:url" property="v:title">Example</a> /
<span rel="v:child" typeof="v:Breadcrumb"><a href="example.com/articles/%articles-category%/" rel="v:url" property="v:title">Articles</a> /
<span rel="v:child" typeof="v:Breadcrumb"><a href="example.com/articles/categ-slug/" rel="v:url" property="v:title">Category name</a> /
<span class="breadcrumb_last">Post Name</span></span></span></span>

Notice example.com/articles/%articles-category%/ where it should be just
example.com/articles/

What is wrong in the code and how can i make it work?

function custom_post_articles() {

    $labels = array(
        // labels
    );

    $args = array(
        'labels'        => $labels,
        'public'        => true,
        'menu_position' => 5,
        'supports'      => array( 'title', 'editor', 'thumbnail', 'excerpt', 'comments' ),
        'has_archive'   => true,
        'hierarchical'  => true,
        'rewrite'       => array('slug' => 'articles/%articles-category%','with_front' => false),
        'query_var'     => true,
        //'rewrite'     => true,
        //'publicly_queryable' => false,
    );
    register_post_type( 'articles', $args );
}
add_action( 'init', 'custom_post_articles' );


function my_taxonomies_product() {
    $labels = array(
        //labels
    );
    $args = array(
        'labels' => $labels,
        'hierarchical'  => true,
        'public'        => true,
        'query_var'     => 'articles-category',

        'rewrite'       =>  array('slug' => 'articles' ),
        '_builtin'      => false,
    );
    register_taxonomy( 'articles-category', 'articles', $args );
}
add_action( 'init', 'my_taxonomies_product', 0 );

add_filter('post_link', 'articles_category_permalink', 1, 3);
add_filter('post_type_link', 'articles_category_permalink', 1, 3);

function articles_category_permalink($permalink, $post_id, $leavename) {

    if (strpos($permalink, '%articles-category%') === FALSE) return $permalink;
        // Get post
        $post = get_post($post_id);
        if (!$post) return $permalink;

        // Get taxonomy terms
        $terms = wp_get_object_terms($post->ID, 'articles-category');
        if (!is_wp_error($terms) && !empty($terms) && is_object($terms[0]))
            $taxonomy_slug = $terms[0]->slug;
        else $taxonomy_slug = 'no-category';

    return str_replace('%articles-category%', $taxonomy_slug, $permalink);
}

1 Answer
1

I solved this way:

Register Custom Post Type:

function custom_post_articles() {

    $labels = array(
        'name'                  => _x( 'Articles', 'post type general name', 'textdomain' ),
        'singular_name'         => _x( 'Article', 'post type singular name', 'textdomain' ),
        // etc...
    );

    $args = array(
        'labels'              => $labels,
        'public'              => true,
        'menu_position'       => 5,                      // Below Posts.
        'menu_icon'           => 'dashicons-megaphone',  // https://developer.wordpress.org/resource/dashicons/
        'capability_type'     => 'post',
        'hierarchical'        => false,                  // False like post, True like page.
        'has_archive'         => true,                   // False like page, True like post.
        'rewrite'             => array(
                                     'slug'       => 'articles/%articles_tax%',
                                     'with_front' => false
                                 ),
        'supports'            => array(
                                     'title',
                                     'editor',
                                     'author',
                                     'thumbnail'
                                )
    );

    register_post_type( 'articles', $args );

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

Register Custom Taxonomy:

function taxonomies_product() {

    $labels = array(
        // labels
    );

    $args = array(
        'labels'            => $labels,
        'public'            => true,
        'hierarchical'      => true,                              // False like tag, True like category.
        'rewrite'           => array(
                                   'slug'         => 'articles',  // Contain lowercase letters and the underscore character (max. 32 char). Default: $taxonomy.
                                   'with_front'   => false,
                                   'hierarchical' => true         // Allow hierarchical urls.
                               )
    );

    register_taxonomy( 'articles_tax', 'articles', $args );

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

RewriteRule for Articles URL Structure:

function rewrite_rules_articles( $rules ) {

    $new = array();
    $new[ 'articles/([^/]+)/(.+)/?$' ] = 'index.php?articles=$matches[2]';
    $new[ 'articles/(.+)/?$' ]         = 'index.php?articles_tax=$matches[1]';

    return array_merge( $new, $rules ); // Put these rules first.

}
add_filter( 'rewrite_rules_array', 'rewrite_rules_articles' );

Replace the placeholder in the URL with the term of the taxonomy:

function handle_placeholder_term_slug( $url, $post ) {

    if ( $post->post_type == 'articles' ) {
        if ( $cats = get_the_terms( $post->ID, 'articles_tax' ) ) {
            $url = str_replace( '%articles_tax%', current( $cats )->slug, $url );
        }
    }

    return $url;

}
add_filter( 'post_type_link', 'handle_placeholder_term_slug', 10, 2 );

Remove the placeholder from the yoast breadcrumbs:

function remove_placeholder_yoast_crumb( $link_output, $link ) {

    if ( $link[ 'text' ] == 'Articles' ) {
        $link_output = str_replace( '/%articles_tax%', '', $link_output );
    }

    /* in the case of a multilingual site
    if ( in_array( $link[ 'text' ], array( 'Articles', 'Artikel', 'Articoli' ) ) ) {
        $link_output = str_replace( '/%articles_tax%', '', $link_output );
    }
    */

    return $link_output;

}
add_filter( 'wpseo_breadcrumb_single_link', 'remove_placeholder_yoast_crumb', 10 ,2 );

Leave a Reply

Your email address will not be published. Required fields are marked *