Remover slug de URLs de post de tipo de post personalizado

39

Parece que todos os recursos da web se baseiam no assunto de remover um tipo de mensagem personalizada, ou seja,

yourdomain.com/CPT-SLUG/post-name 

agora são soluções muito desatualizadas, muitas vezes referenciando as instalações do pré-WP versão 3.5. Um comum é:

'rewrite'   => array( 'slug' => false, 'with_front' => false ),  

dentro da sua função register_post_type. Isso não funciona mais e é enganoso. Então eu peço à comunidade no terceiro trimestre de 2018 à beira do WordPress 5 ...

Quais são as maneiras modernas e eficientes de remover o Slug de tipo de postagem de um URL de postagem de um tipo de postagem personalizado de dentro do argumento de reconfiguração ou em qualquer outro lugar?

ATUALIZAÇÃO: Parece haver várias maneiras de forçar isso para trabalhar com regex. Especificamente, a resposta de Jan Beck deve estar sempre disposto a monitorar a criação de conteúdo para garantir que não sejam criados nomes conflitantes de páginas / postagens. No entanto, estou convencido de que essa é uma grande fraqueza no núcleo do WP, onde deve ser tratada por nós. . Ambos como uma opção / gancho ao criar um CPT ou um conjunto avançado de opções para permalinks. Por favor, apoiem o bilhete da pista.

Nota de rodapé: Por favor, apoie este bilhete trac assistindo / promovendo-o: enlace

    
por TR3B 28.09.2015 / 18:18
fonte

10 respostas

56

O código a seguir funcionará, mas você só precisa ter em mente que os conflitos podem acontecer facilmente se o slug do seu tipo de post personalizado for o mesmo que uma página ou um slug de postagem ...

Primeiro, removeremos o slug do permalink:

function na_remove_slug( $post_link, $post, $leavename ) {

    if ( 'events' != $post->post_type || 'publish' != $post->post_status ) {
        return $post_link;
    }

    $post_link = str_replace( '/' . $post->post_type . '/', '/', $post_link );

    return $post_link;
}
add_filter( 'post_type_link', 'na_remove_slug', 10, 3 );

Apenas remover a lesma não é suficiente. Agora, você receberá uma página 404 porque o WordPress espera apenas que as postagens e as páginas se comportem dessa maneira. Você também precisará adicionar o seguinte:

function na_parse_request( $query ) {

    if ( ! $query->is_main_query() || 2 != count( $query->query ) || ! isset( $query->query['page'] ) ) {
        return;
    }

    if ( ! empty( $query->query['name'] ) ) {
        $query->set( 'post_type', array( 'post', 'events', 'page' ) );
    }
}
add_action( 'pre_get_posts', 'na_parse_request' );

Basta alterar "eventos" para o seu tipo de postagem personalizado e pronto. Talvez seja necessário atualizar seus permalinks.

    
por Nate Allen 30.09.2015 / 22:45
fonte
11

Eu tentei descobrir isso não muito tempo atrás e a resposta curta do que eu sei é não . Não de dentro do argumento de reescrita, pelo menos.

A longa explicação se torna aparente se você olhar o código real de register_post_type em wp-includes / post.php linha 1454 :

add_permastruct( $post_type, "{$args->rewrite['slug']}/%$post_type%", $permastruct_args );

Você pode ver os prefixos $args->rewrite['slug'] na tag %$post_type% reescrita. Pode-se pensar "vamos apenas definir o slug para null then" até você olhar algumas linhas para cima:

if ( empty( $args->rewrite['slug'] ) )
    $args->rewrite['slug'] = $post_type;

Você pode ver que a função sempre espera um valor slug que não esteja vazio e use o tipo de postagem.

    
por Jan Beck 30.09.2015 / 16:01
fonte
11

Escreva o código a seguir no registro de taxonomia.

'rewrite' => [
  'slug' => '/',
  'with_front' => false
]

A coisa mais importante que você precisa fazer depois de alterar o código

Depois de alterar o documento de taxonomia do seu tipo de postagem personalizado, tente ir para Configurações > Permalinks e salvar novamente suas configurações , senão você receberá 404 páginas não encontradas.

Verifique aqui a melhor solução: enlace

    
por Mayank Dudakiya 12.04.2017 / 20:16
fonte
6

Em resposta a minha resposta anterior : você poderia, é claro, definir o parâmetro rewrite como false ao registrar um novo tipo de postagem e lidar com as regras de reconfiguração você mesmo assim

<?php
function wpsx203951_custom_init() {

    $post_type = 'event';
    $args = (object) array(
        'public'      => true,
        'label'       => 'Events',
        'rewrite'     => false, // always set this to false
        'has_archive' => true
    );
    register_post_type( $post_type, $args );

    // these are your actual rewrite arguments
    $args->rewrite = array(
        'slug' => 'calendar'
    );

    // everything what follows is from the register_post_type function
    if ( is_admin() || '' != get_option( 'permalink_structure' ) ) {

        if ( ! is_array( $args->rewrite ) )
            $args->rewrite = array();
        if ( empty( $args->rewrite['slug'] ) )
            $args->rewrite['slug'] = $post_type;
        if ( ! isset( $args->rewrite['with_front'] ) )
            $args->rewrite['with_front'] = true;
        if ( ! isset( $args->rewrite['pages'] ) )
            $args->rewrite['pages'] = true;
        if ( ! isset( $args->rewrite['feeds'] ) || ! $args->has_archive )
            $args->rewrite['feeds'] = (bool) $args->has_archive;
        if ( ! isset( $args->rewrite['ep_mask'] ) ) {
            if ( isset( $args->permalink_epmask ) )
                $args->rewrite['ep_mask'] = $args->permalink_epmask;
            else
                $args->rewrite['ep_mask'] = EP_PERMALINK;
        }

        if ( $args->hierarchical )
            add_rewrite_tag( "%$post_type%", '(.+?)', $args->query_var ? "{$args->query_var}=" : "post_type=$post_type&pagename=" );
        else
            add_rewrite_tag( "%$post_type%", '([^/]+)', $args->query_var ? "{$args->query_var}=" : "post_type=$post_type&name=" );

        if ( $args->has_archive ) {
            $archive_slug = $args->has_archive === true ? $args->rewrite['slug'] : $args->has_archive;
            if ( $args->rewrite['with_front'] )
                $archive_slug = substr( $wp_rewrite->front, 1 ) . $archive_slug;
            else
                $archive_slug = $wp_rewrite->root . $archive_slug;

            add_rewrite_rule( "{$archive_slug}/?$", "index.php?post_type=$post_type", 'top' );
            if ( $args->rewrite['feeds'] && $wp_rewrite->feeds ) {
                $feeds = '(' . trim( implode( '|', $wp_rewrite->feeds ) ) . ')';
                add_rewrite_rule( "{$archive_slug}/feed/$feeds/?$", "index.php?post_type=$post_type" . '&feed=$matches[1]', 'top' );
                add_rewrite_rule( "{$archive_slug}/$feeds/?$", "index.php?post_type=$post_type" . '&feed=$matches[1]', 'top' );
            }
            if ( $args->rewrite['pages'] )
                add_rewrite_rule( "{$archive_slug}/{$wp_rewrite->pagination_base}/([0-9]{1,})/?$", "index.php?post_type=$post_type" . '&paged=$matches[1]', 'top' );
        }

        $permastruct_args = $args->rewrite;
        $permastruct_args['feed'] = $permastruct_args['feeds'];
        add_permastruct( $post_type, "%$post_type%", $permastruct_args );
    }
}
add_action( 'init', 'wpsx203951_custom_init' );

Você pode ver que a chamada add_permastruct agora não inclui mais a lesma. Eu testei dois cenários:

  1. Quando criei uma página com o slug "calendar", essa página é sobrescrita pelo arquivo do tipo post que também usa o slug "calendar".

  • Quando criei uma página com o slug "meu-evento" e um evento (CPT) com o slug "meu-evento", o tipo de postagem personalizado é exibido.
  • Quaisquer outras páginas também não funcionam. Se você observar a figura acima, fica claro o porquê: a regra de tipo de postagem personalizada sempre corresponderá a um slug de página. Como o WordPress não tem como identificar se é uma página ou um tipo de post personalizado que não existe, ele retornará 404. É por isso que você precisa de um slug para identificar a página ou o CPT. Uma possível solução seria interceptar o erro e procurar uma página que possa existir semelhante a essa resposta .
  • por Jan Beck 02.10.2015 / 14:13
    fonte
    2

    Olhando as respostas aqui, acho que há espaço para uma solução melhor que combina algumas coisas que aprendi acima e adiciona autodetecção e prevenção de duplicatas de slugs.

    OBSERVAÇÃO: lembre-se de alterar 'custom_post_type' para o seu próprio nome de CPT em todo o meu exemplo abaixo. Existem muitas ocorrências e um 'localizar / substituir' é uma maneira fácil de capturar todas elas. Todo este código pode ir em suas funções.php ou em um plugin.

    Passo 1: Desative as novas gravações no seu tipo de postagem personalizada, definindo reescrever como 'false' ao registrar a postagem:

    register_post_type( 'custom_post_type',
        array(
            'rewrite' => false
        )
    );
    

    Etapa 2: adicione manualmente nossas regras personalizadas à parte do WordPress para o nosso custom_post_type

    function custom_post_type_rewrites() {
        add_rewrite_rule( '[^/]+/attachment/([^/]+)/?$', 'index.php?attachment=$matches[1]', 'bottom');
        add_rewrite_rule( '[^/]+/attachment/([^/]+)/trackback/?$', 'index.php?attachment=$matches[1]&tb=1', 'bottom');
        add_rewrite_rule( '[^/]+/attachment/([^/]+)/feed/(feed|rdf|rss|rss2|atom)/?$', 'index.php?attachment=$matches[1]&feed=$matches[2]', 'bottom');
        add_rewrite_rule( '[^/]+/attachment/([^/]+)/(feed|rdf|rss|rss2|atom)/?$', 'index.php?attachment=$matches[1]&feed=$matches[2]', 'bottom');
        add_rewrite_rule( '[^/]+/attachment/([^/]+)/comment-page-([0-9]{1,})/?$', 'index.php?attachment=$matches[1]&cpage=$matches[2]', 'bottom');
        add_rewrite_rule( '[^/]+/attachment/([^/]+)/embed/?$', 'index.php?attachment=$matches[1]&embed=true', 'bottom');
        add_rewrite_rule( '([^/]+)/embed/?$', 'index.php?custom_post_type=$matches[1]&embed=true', 'bottom');
        add_rewrite_rule( '([^/]+)/trackback/?$', 'index.php?custom_post_type=$matches[1]&tb=1', 'bottom');
        add_rewrite_rule( '([^/]+)/page/?([0-9]{1,})/?$', 'index.php?custom_post_type=$matches[1]&paged=$matches[2]', 'bottom');
        add_rewrite_rule( '([^/]+)/comment-page-([0-9]{1,})/?$', 'index.php?custom_post_type=$matches[1]&cpage=$matches[2]', 'bottom');
        add_rewrite_rule( '([^/]+)(?:/([0-9]+))?/?$', 'index.php?custom_post_type=$matches[1]', 'bottom');
        add_rewrite_rule( '[^/]+/([^/]+)/?$', 'index.php?attachment=$matches[1]', 'bottom');
        add_rewrite_rule( '[^/]+/([^/]+)/trackback/?$', 'index.php?attachment=$matches[1]&tb=1', 'bottom');
        add_rewrite_rule( '[^/]+/([^/]+)/feed/(feed|rdf|rss|rss2|atom)/?$', 'index.php?attachment=$matches[1]&feed=$matches[2]', 'bottom');
        add_rewrite_rule( '[^/]+/([^/]+)/(feed|rdf|rss|rss2|atom)/?$', 'index.php?attachment=$matches[1]&feed=$matches[2]', 'bottom');
        add_rewrite_rule( '[^/]+/([^/]+)/comment-page-([0-9]{1,})/?$', 'index.php?attachment=$matches[1]&cpage=$matches[2]', 'bottom');
        add_rewrite_rule( '[^/]+/([^/]+)/embed/?$', 'index.php?attachment=$matches[1]&embed=true', 'bottom');
    }
    add_action( 'init', 'custom_post_type_rewrites' );
    

    NOTA: Dependendo das suas necessidades, você pode modificar as reescritas acima (desative os trackbacks? feeds ?, etc). Estes representam os tipos de reescrita "padrão" que teriam sido gerados se você não desativasse as reescritas na etapa 1

    Etapa 3: torne os permalinks no seu tipo de postagem personalizado "bonito" novamente

    function custom_post_type_permalinks( $post_link, $post, $leavename ) {
        if ( isset( $post->post_type ) && 'custom_post_type' == $post->post_type ) {
            $post_link = home_url( $post->post_name );
        }
    
        return $post_link;
    }
    add_filter( 'post_type_link', 'custom_post_type_permalinks', 10, 3 );
    

    NOTA: Você pode parar por aqui se não estiver preocupado com a criação de uma postagem (duplicada) conflitante em outro tipo de postagem que criará uma situação em que apenas uma delas poderá ser carregada quando a página for solicitada. / em>

    Etapa 4: Impedir duplicatas de slugs de postagem

    function prevent_slug_duplicates( $slug, $post_ID, $post_status, $post_type, $post_parent, $original_slug ) {
        $check_post_types = array(
            'post',
            'page',
            'custom_post_type'
        );
    
        if ( ! in_array( $post_type, $check_post_types ) ) {
            return $slug;
        }
    
        if ( 'custom_post_type' == $post_type ) {
            // Saving a custom_post_type post, check for duplicates in POST or PAGE post types
            $post_match = get_page_by_path( $slug, 'OBJECT', 'post' );
            $page_match = get_page_by_path( $slug, 'OBJECT', 'page' );
    
            if ( $post_match || $page_match ) {
                $slug .= '-duplicate';
            }
        } else {
            // Saving a POST or PAGE, check for duplicates in custom_post_type post type
            $custom_post_type_match = get_page_by_path( $slug, 'OBJECT', 'custom_post_type' );
    
            if ( $custom_post_type_match ) {
                $slug .= '-duplicate';
            }
        }
    
        return $slug;
    }
    add_filter( 'wp_unique_post_slug', 'prevent_slug_duplicates', 10, 6 );
    

    NOTA: Isto irá acrescentar a string '-duplicate' ao final de qualquer slug duplicado. Esse código não pode evitar slugs duplicados se eles já existirem antes da implementação dessa solução. Certifique-se de verificar se há duplicatas primeiro.

    Eu adoraria ouvir de qualquer outra pessoa que faça isso para ver se funcionou bem para eles também.

        
    por Matt Keys 06.10.2017 / 00:51
    fonte
    0

    Você não precisa de tanto código rígido. Basta usar o plugin leve:

    Tem opções personalizáveis.

        
    por T.Todua 25.02.2017 / 23:12
    fonte
    0

    e podemos fazer algumas alterações na função acima mencionada:

    function na_parse_request( $query ) {
    
    if ( ! $query->is_main_query() || 2 != count( $query->query ) || ! isset( $query->query['page'] ) ) {
        return;
    }
    
    if ( ! empty( $query->query['name'] ) ) {
        $query->set( 'post_type', array( 'post', 'events', 'page' ) );
    }
    }
    

    para:

    function na_parse_request( $query ) {
    
    if ( ! $query->is_main_query() || 2 != count( $query->query ) || ! isset( $query->query['page'] ) ) {
        return;
    }
    
    if ( ! empty( $query->query['name'] ) ) {
    
        global $wpdb;
        $pt = $wpdb->get_var(
            "SELECT post_type FROM '{$wpdb->posts}' " .
            "WHERE post_name = '{$query->query['name']}'"
        );
        $query->set( 'post_type', $pt );
    }
    }
    

    para definir o valor correto de post_type.

        
    por Max Kondrachuk 01.03.2017 / 12:50
    fonte
    0

    Isso funcionou para mim:   'rewrite' => array('slug' => '/')

        
    por Malki Mohamed 03.05.2017 / 18:39
    fonte
    0

    Para quem lê isso e teve problemas com postagens de crianças como eu, achei que a melhor maneira era adicionar suas próprias regras de reescrita.

    O principal problema que eu tive foi que o WordPress trata o redirecionamento de páginas que são 2 níveis (posts de crianças) profundamente um pouco diferente do que trata de 3 níveis de profundidade (filho de posts de crianças).

    Isso significa que quando eu tiver / post-type / post-name / post-child / eu posso usar / post-name / post-child e ele irá me redirecionar para aquele com post-type na frente, mas se eu tiver pós-tipo / pós-nome / pós-filho / pós-neto, então não posso usar pós-nome / pós-filho / pós-neto.

    Dando uma olhada nas regras de reescrita, parece que ele combina com outras coisas além de pagename no primeiro e segundo níveis (acho que o segundo nível corresponde ao anexo) e faz alguma coisa lá para redirecioná-lo para a postagem apropriada. A três níveis de profundidade não funciona.

    A primeira coisa que você precisa fazer é remover o link do tipo de postagem das crianças também. Essa lógica deve acontecer aqui se você olhar a resposta de Nate Allen acima:

    $post_link = str_replace( '/' . $post->post_type . '/', '/', $post_link );
    

    Eu mesmo usei uma mistura de diferentes condicionais para verificar se o post tinha filhos e outras coisas, a fim de obter o permalink correto. Esta parte não é muito complicada e você encontrará exemplos de pessoas fazendo isso em outro lugar.

    O próximo passo é onde as coisas mudam da resposta dada. Em vez de adicionar coisas à consulta principal (que funcionou para postagens personalizadas e seus filhos, mas não as outras crianças) eu adicionei uma reescrita que foi para o fundo das regras do WordPress para que se pagename não check-out e estava prestes a acertar um 404 faria uma última verificação para ver se uma página dentro do tipo de postagem personalizada tinha o mesmo nome senão jogaria fora o 404.

    Aqui está a regra de reescrita que usei assumindo que 'event' é o nome do seu CPT

    function rewrite_rules_for_removing_post_type_slug()
    {
        add_rewrite_rule(
            '(.?.+?)?(:/([0-9]+))?/?$',
            'index.php?event=$matches[1]/$matches[2]&post_type=event',
            'bottom'
        );
    }
    
    add_action('init', 'rewrite_rules_for_removing_post_type_slug', 1, 1);
    

    Espero que isso ajude alguém, eu não consegui encontrar mais nada que tenha a ver com o filho de postagens de crianças e remover a lesma delas.

        
    por Moe Loubani 29.05.2017 / 05:34
    fonte
    -2

    Você pode fazer isso de uma forma muito simples.

    1) Copie essa função para o functions.php :

    do seu tema
    function changeURL ($id)
    {
        /* Get the slug you want to remove. */
        global $post;
        $slug = get_post($post)->post_name;
    
        $post_type = get_post_type ($id);
        $standard_posts = array("post", "page", "attachment", "revision", "nav_menu_item");
        /* 
            If the type of the current post is a custom one, use Javascript to
            replace the $slug for the default URL of the post.
        */
        if (!in_array ($post_type, $standard_posts))
        {
            echo '<script type="text/javascript">
                var stateObj = { register: "' . $slug . '" };
                history.pushState(stateObj, "ignore_this", "../?p='.$id.'");
                </script>';
        }
    }
    


    2) Chame essa função para o single.php do seu tema abaixo do while do Loop:

    <?php /* The loop */ ?>
    <?php while ( have_posts() ) : the_post();?>
    
        <?php changeURL (get_the_ID ()); ?>
        /* etc. */
    
    <?php endwhile; ?>
    


    E deixe o Javascript fazer a mágica :)

    Atualização:

    Resolvidos os inconvenientes apontados pelo @kraftner nos comentários. Agora, o changeURL() substituirá o permalink pelo URL padrão na barra de endereço.

        
    por Daniel Muñoz Parsapoormoghadam 03.10.2015 / 11:34
    fonte