web-dev-qa-db-fra.com

Plusieurs types de publication - partagez-vous le même slug ReWrite?

J'ai rencontré un autre problème 404 merveilleux. J'essaie d'avoir 2 types de publication séparés qui partagent le même slug de réécriture. J'ai effacé mes règles de réécriture, et lorsque je teste seulement un des CPT, l'autre obtient un 404. Ma réécriture que je souhaite utiliser pour les deux est la suivante:

'rewrite' => array('slug' => 'team/%teamtype%'),

Quelqu'un sait comment gérer cela?

add_action( 'init', 'create_rider_type' );

function create_rider_type() {

register_post_type('riders', 
array(  
    'description' => 'rider custom post type',
    'show_ui' => true,
    'menu_position' => 5,
    'menu_icon' => get_stylesheet_directory_uri() . '/images/riders.png',
    'exclude_from_search' => false,
    'labels' => array(
        'name' => 'Team Riders',
        'singular_name' => 'Rider',
        'add_new' => 'Add New rider',
        'add_new_item' => 'Add New rider',
        'edit' => 'Edit riders',
        'edit_item' => 'Edit rider',
        'new_item' => 'New rider',
        'view' => 'View rider',
        'view_item' => 'View rider',
        'search_items' => 'Search riders',
        'not_found' => 'No riders found',
        'not_found_in_trash' => 'No riders found in Trash',
        'parent' => 'Parent rider',
    ),
    'hierarchical' => false,
    'supports' => array('title','editor','excerpt', 'trackbacks','custom-fields', 'comments','revisions','thumbnail','author','page-attributes'),
    'public' => true,
    'rewrite' => array('slug' => 'team/%teamtype%'),
    'taxonomies' => array('teamtype')
    ) 
);


}





add_action( 'init', 'create_sponsor_type' );

function create_sponsor_type() {

register_post_type('sponsors', 
array(  
    'description' => 'sponsor custom post type',
    'show_ui' => true,
    'menu_position' => 5,
    'menu_icon' => get_stylesheet_directory_uri() . '/images/sponsors.png',
    'exclude_from_search' => false,
    'labels' => array(
        'name' => 'Team sponsors',
        'singular_name' => 'sponsor',
        'add_new' => 'Add New sponsor',
        'add_new_item' => 'Add New sponsor',
        'edit' => 'Edit sponsors',
        'edit_item' => 'Edit sponsor',
        'new_item' => 'New sponsor',
        'view' => 'View sponsor',
        'view_item' => 'View sponsor',
        'search_items' => 'Search sponsors',
        'not_found' => 'No sponsors found',
        'not_found_in_trash' => 'No sponsors found in Trash',
        'parent' => 'Parent sponsor',
    ),
    'hierarchical' => false,
    'supports' => array('title','editor','excerpt', 'trackbacks','custom-fields', 'comments','revisions','thumbnail','author','page-attributes'),
    'public' => true,
    'rewrite' => array('slug' => 'team/%teamtype%'),
    'taxonomies' => array('teamtype')
    ) 
);

}

************* Mettre à jour* ** * ** * ** * ** * ** * ** * ** * ** * ** * ** * ** * *

Le code de réécriture CPT original que j'ai posté a été simplifié pour que je puisse aller plus droit au but. Cependant, il est peut-être plus logique de voir comment je gère ces permaliens avec ma taxonomie personnalisée. J'ai mis à jour le code pour montrer.

Je souhaite vraiment les garder en tant que types de poste séparés - pour l'organisation ainsi que des métaboxes séparés pour chacun. Veuillez vérifier les réécritures mises à jour pour les CPT, ainsi que ma configuration de taxonomie ci-dessous:

add_action( 'init', 'create_team_taxonomies' );

function create_team_taxonomies() {
register_taxonomy( 
'teamtype', 
array('riders','sponsors'),
array( 
    'labels' => array(
        'name' => 'Team Types',
        'singular_name' => 'Team Type',
        'search_items' =>  'Search Team Types',
        'popular_items' => 'Popular Team Types',
        'all_items' => 'All Team Types',
        'parent_item' => 'Parent Team Type',
        'parent_item_colon' => 'Parent Team Type:',
        'edit_item' => 'Edit Team Type', 
        'update_item' => 'Update Team Type',
        'add_new_item' => 'Add New Team Type',
        'new_item_name' => 'New Team Type Name'
    ), 
'hierarchical' => true, 
'public' => true,
'show_ui' => true,
'query_var' => 'teamtype',
'show_tagcloud' => true,
'rewrite' => array( 'slug' => 'team', 'with_front' => false) 
) 
);

}

Et voici comment je configure la réécriture lorsque je sélectionne la taxonomie et publie le message:

add_filter('post_link', 'teamtypepermalink', 10, 3);
add_filter('post_type_link', 'teamtypepermalink', 10, 3);

function teamtypepermalink($permalink, $post_id, $leavename) {
if (strpos($permalink, '%teamtype%') === FALSE) return $permalink;

    // Get post
    $post = get_post($post_id);
    if (!$post) return $permalink;

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

return str_replace('%teamtype%', $taxonomy_slug, $permalink);
}
4
Joe

Je viens de faire un projet où deux types de publication personnalisés devaient partager le même slug. L'astuce consiste à écraser les vars de requête via le filtre request. Appelons les types de messages 'foo' et 'bar', et ils partageront le slug 'foo'.

Le code suivant est approximatif et de mémoire uniquement. Sel au goût, ne pas copier-coller:

add_filter('request', 'overwriteQueryVars', 10, 1);

function overwriteQueryVars($query)
{
    if ( empty($query['post_type']) || $query['post_type']!='foo' ) {
        return $query;
    }

    // Run an SQL query that looks like this, against both post types
    $sql = "SELECT ID FROM wp_posts WHERE post_type='foo' and post_name='%s'";
    $post_name = urlencode($query['name']);

    // If you've found that the row exists for post_type 'bar' but not 'foo',
    // then simply return the $query array unaltered
    if ( in_foo_but_not_bar ) {
        return $query;
    }

    // If you've found that the row exists for post_type 'bar' but not 'foo',
    // then rewrite the $query array:

    // Original:
    $query = array (
        'page' => '',
        'foo' => 'some-Nice-post',
        'post_type' => 'foo',
        'name' => 'some-Nice-post',
    );

    // Make it look like this:
    $query = array (
        'page' => '',
        'bar' => 'some-Nice-post',
        'post_type' => 'bar',
        'name' => 'some-Nice-post',
    );

}
1
dotancohen

Autant que je sache, vous ne pouvez pas faire ça. Chaque slug est converti en un élément query_vars qui interroge un type d'objet spécifique (taxonomie ou type de publication). Si vous analysez votre WP_Query, vous verrez que le premier type de message est interrogé.

Peut-être qu'un WP Ninja ici peut nous éclairer sur ce point, mais je suis presque sûr que vous ne pouvez pas le faire. Ou du moins, vous ne devriez pas.

1
MZAweb

Comme les CPT (et les posts/pages, d'ailleurs) sont construits, ce n'est pas possible. Le slug est réservé au type spécifique, avec la compréhension/hypothèse que 2 CPT = 2 types de contenu différents.

sur la base de votre code, il semble presque que chacun des éléments que vous avez dans le CPT serait mieux servi comme une taxonomie personnalisée, les deux étant rattachés à un seul CPT (je suppose un événement?)

1
Norcross

Je sais que cette question est très ancienne, mais lorsque je cherchais une solution à un problème similaire, cette question se rapprochait le plus de ce que j'essayais de réaliser, et comme elle est apparue dans mes recherches, j'ai pensé qu'il pourrait ne pas y en avoir toutes les meilleures solutions disponibles. J'ajouterai donc la solution que j'ai proposée ci-dessous au cas où cela pourrait aider quelqu'un ultérieurement avec un problème similaire.

J'avais un problème similaire. Je voulais avoir un nouveau type de message personnalisé qui partagerait le slug avec un autre type de message. Dans mon cas, j'avais un type de message appelé country-info et je souhaitais utiliser la même structure de permalien que le type de message page standard.

En d'autres termes, je voulais qu'il soit accessible en utilisant example.com/page-name/ au lieu de example.com/country-info/page-name.

Voici comment je l'ai résolu:

// I found it easiest to grab the request in the parse_request hook. There you can see
// the requested slug, as well as if the requested page existed or not.

add_action('parse_request', 'overwriteRequest', 10, 1);
function overwriteRequest($query) {

    // If the request matched an existing page, the query_vars array will contain the
    // post_type, but otherwise it will only contain an error.
    // So we only execute our code if the post_type is empty
    // On the top page, the query_vars is an empty array, so we check for that too!
    if ( count($query->query_vars) > 0 && empty($query->query_vars['post_type'])) {

        // The request contains the string that was requested.
        $pageName = $query->request;
        $postType = 'country-info';

        // Check if post with the requested slug exists in your custom post type
        $result = get_posts(array(
            'post_type' => $postType,
            'name' => $pageName
        ));

        // If it doesn't, just return the query
        if (count($result) < 1) {

            return $query;

        // If it does, create a new query_vars array to replace the old one.
        } else {
            $new_query = array(
                'page' => '',
                'country-info' => $pageName,
                'post_type' => $postType,
                'name' => $pageName
            );
            $query->query_vars = $new_query;
            return $query;
        }

    } else {
        return $query;
    }
}

Notez s'il vous plaît:

Dans mon cas, les demandes que je recherchais se trouvaient toutes au niveau racine du domaine, comme example.com/page-name, mais si votre type de publication personnalisé se trouvait dans un répertoire tel que example.com/some-directory/post-name/, vous devrez alors modifier une chose dans le code:

$pageName = $query->request;

doit être

$pageName = preg_replace('/my-directory-name\//', '', $query->request)

Sinon, get_posts tentera de trouver un article dans lequel le slug contiendra votre répertoire, ce qui vous donnera toujours zéro résultat. Ce preg_replace supprime simplement votre nom de répertoire de la chaîne.

N'oubliez pas de remplacer my-directory-name par le nom de répertoire réel!

Cette solution a été testée et fonctionne sur WordPress 4.9.7

0
Azer

Vos règles de réécriture se remplaceront mutuellement et WordPress interrogera un seul des types de publication. Je pense que c'est le dernier qui est enregistré et qui "gagne", donc /testslug/bmw/ demandera toujours une publication avec slug bmw et une publication de type sponsors. Si vous allez à /testslug/some-name/ et que some-name est un coureur, il demandera toujours le type de message sponsors et le message slug some-name. Il ne trouvera aucun message et vous donnera donc un 404. Cela se produit dans la requête "par défaut" que WordPress effectuera pour vous, avant de charger la page de modèle; vous ne pourrez donc pas résoudre ce problème dans votre fichier de modèle single-sponsors.php, par exemple ( vous pourriez dans 404.php, mais alors ça devient moche).

La solution la plus propre consiste à remplacer une partie de la logique qui effectue l'analyse de l'URL et à lui faire accepter une URL "ambiguë". Testez s'il s'agit d'un pilote ou d'un sponsor et modifiez les paramètres afin que WordPress continue avec un pilote ou un sponsor. Mike une fois fourni un moyen de le faire avec des pages et des taxonomies, il devrait être possible d’étendre cela au travail avec des posts uniquement.

0
Jan Fabry