Como definir o relacionamento pai-filho entre diferentes tipos de post personalizado

10

Acabei de criar um relacionamento pós / pai entre um tipo de postagem "episódios" e um tipo de postagem "série de desenhos animados".

Eu usei esse código para adicionar na caixa meta para atribuir o pai de outro tipo de postagem:

add_action('admin_menu', function() {
    remove_meta_box('pageparentdiv', 'episodes', 'normal');
});
add_action('add_meta_boxes', function() {
    add_meta_box('episodes-parent', 'Cartoon Series', 'episodes_attributes_meta_box', 'episodes', 'side', 'default');
});

function episodes_attributes_meta_box($post) {
    $post_type_object = get_post_type_object($post->post_type);
    if ( $post_type_object->hierarchical ) {
        $pages = wp_dropdown_pages(array('post_type' => 'cartoon-series', 'selected' => $post->post_parent, 'name' => 'parent_id', 'show_option_none' => __('(no parent)'), 'sort_column'=> 'menu_order, post_title', 'echo' => 0));
        if ( ! empty($pages) ) {
            echo $pages;
        } // end empty pages check
    } // end hierarchical check.
}

Isso funcionou na tela do administrador ao permitir que eu definisse a série como pai / mãe do episódio, mas quando tento visualizar a postagem, recebo um 404. A estrutura da URL é:

domain/episodes/series-name/episode-name

O URL da série é:

domain/cartoon-series/series-name

Eu gostaria que o URL do episódio fosse:

domain/cartoon-series/series-name/episode-name

O que estou perdendo? É possível fazer uma postagem inteira digitar o filho de outro tipo de postagem? Então, eu poderia até conseguir que o URL da lista de episódios fosse:

domain/cartoon-series/series-name/episodes

Obrigado! Matt

Conforme solicitado, aqui está o código dos dois tipos de post personalizado em questão:

$labels = array(
    "name" => "Cartoon Series",
    "singular_name" => "Cartoon Series",
    "menu_name" => "Cartoon Series",
    "all_items" => "All Cartoon Series",
    "add_new" => "Add New",
    "add_new_item" => "Add New Cartoon Series",
    "edit" => "Edit",
    "edit_item" => "Edit Cartoon Series",
    "new_item" => "New Cartoon Series",
    "view" => "View",
    "view_item" => "View Cartoon Series",
    "search_items" => "Search Cartoon Series",
    "not_found" => "No Cartoon Series Found",
    "not_found_in_trash" => "No Cartoon Series Found in Trash",
    "parent" => "Parent Cartoon Series",
    );

$args = array(
    "labels" => $labels,
    "description" => "",
    "public" => true,
    "show_ui" => true,
    "has_archive" => true,
    "show_in_menu" => true,
    "exclude_from_search" => false,
    "capability_type" => "post",
    "map_meta_cap" => true,
    "hierarchical" => true,
    "rewrite" => array( "slug" => "cartoon-series", "with_front" => true ),
    "query_var" => true,
    "supports" => array( "title", "revisions", "thumbnail" ),           );
register_post_type( "cartoon-series", $args );

$labels = array(
    "name" => "Episodes",
    "singular_name" => "Episode",
    );

$args = array(
    "labels" => $labels,
    "description" => "",
    "public" => true,
    "show_ui" => true,
    "has_archive" => true,
    "show_in_menu" => true,
    "exclude_from_search" => false,
    "capability_type" => "post",
    "map_meta_cap" => true,
    "hierarchical" => true,
    "rewrite" => array( "slug" => "episodes", "with_front" => true ),
    "query_var" => true,
    "supports" => array( "title", "revisions", "thumbnail" ),           );
register_post_type( "episodes", $args );

Estou usando o plug-in CPT UI, por isso não posso editar esse código diretamente. Esse é apenas o código de exportação fornecido pela interface do CPT.

Eu não tenho nenhum outro código que ligue os dois CPTs. Talvez seja disso que estou perdendo. Acabei de encontrar o código on-line que coloca o metabox na página para fazer a vinculação. Não é suficiente fazer o trabalho? Parece que define o post_parent.

Obrigado! Matt

    
por Mattaton 13.03.2015 / 23:20

3 respostas

8

Finalmente, encontrei uma solução de trabalho. A série de desenhos animados pode ser registrada como você fez, mas episódios de tipos de postagem personalizados não podem ser hierárquicos (acho que o WordPress espera que o conteúdo pai seja do mesmo tipo que o conteúdo filho se o relacionamento for definido usando post_parent in wp_posts database table).

Ao registrar episódios, a regra de reconfiguração deve ser definida para o slug desejado, ou seja, cartoon-series/%series_name% . Em seguida, podemos filtrar o link de episódios para substituir %series_name% pelo nome real do tipo de postagem paicartoon-series e uma regra de regravação para dizer ao WordPress quando um tipo de postagem de série de desenhos animados é solicitado e quando é um episódio.

add_action('init', function(){
    $labels = array(
        "name" => "Cartoon Series",
        "singular_name" => "Cartoon Series",
        "menu_name" => "Cartoon Series",
        "all_items" => "All Cartoon Series",
        "add_new" => "Add New",
        "add_new_item" => "Add New Cartoon Series",
        "edit" => "Edit",
        "edit_item" => "Edit Cartoon Series",
        "new_item" => "New Cartoon Series",
        "view" => "View",
        "view_item" => "View Cartoon Series",
        "search_items" => "Search Cartoon Series",
        "not_found" => "No Cartoon Series Found",
        "not_found_in_trash" => "No Cartoon Series Found in Trash",
        "parent" => "Parent Cartoon Series",
    );

    $args = array(
        "labels" => $labels,
         "description" => "",
        "public" => true,
        "show_ui" => true,
        "has_archive" => true,
        "show_in_menu" => true,
        "exclude_from_search" => false,
        "capability_type" => "post",
        "map_meta_cap" => true,
        "hierarchical" => true,
        "rewrite" => array( "slug" => "cartoon-series", "with_front" => true ),
        "query_var" => true,
        "supports" => array( "title", "revisions", "thumbnail" )
    );

    register_post_type( "cartoon-series", $args );

    $labels = array(
        "name" => "Episodes",
        "singular_name" => "Episode",
    );

    $args = array(
        "labels" => $labels,
        "description" => "",
        "public" => true,
        "show_ui" => true,
        "has_archive" => true,
        "show_in_menu" => true,
        "exclude_from_search" => false,
        "capability_type" => "post",
        "map_meta_cap" => true,
        "hierarchical" => false,
        "rewrite" => array( "slug" => "cartoon-series/%series_name%", "with_front" => true ),
        "query_var" => true,
        "supports" => array( "title", "revisions", "thumbnail" )
    );

    register_post_type( "episodes", $args );

});

add_action('add_meta_boxes', function() {
    add_meta_box('episodes-parent', 'Cartoon Series', 'episodes_attributes_meta_box', 'episodes', 'side', 'default');
});

function episodes_attributes_meta_box($post) {
        $pages = wp_dropdown_pages(array('post_type' => 'cartoon-series', 'selected' => $post->post_parent, 'name' => 'parent_id', 'show_option_none' => __('(no parent)'), 'sort_column'=> 'menu_order, post_title', 'echo' => 0));
        if ( ! empty($pages) ) {
            echo $pages;
        } // end empty pages check
}

add_action( 'init', function() {

    add_rewrite_rule( '^cartoon-series/(.*)/([^/]+)/?$','index.php?episodes=$matches[2]','top' );

});

add_filter( 'post_type_link', function( $link, $post ) {
    if ( 'episodes' == get_post_type( $post ) ) {
        //Lets go to get the parent cartoon-series name
        if( $post->post_parent ) {
            $parent = get_post( $post->post_parent );
            if( !empty($parent->post_name) ) {
                return str_replace( '%series_name%', $parent->post_name, $link );
            }
        } else {
            //This seems to not work. It is intented to build pretty permalinks
            //when episodes has not parent, but it seems that it would need
            //additional rewrite rules
            //return str_replace( '/%series_name%', '', $link );
        }

    }
    return $link;
}, 10, 2 );

OBSERVAÇÃO : Lembre-se de liberar regras de regravação depois de salvar o código acima e antes de testá-lo. Vá para wp-admin/options-permalink.php e clique em salvar para regerenar as regras de regravação.

NOTA 2 : É provável que mais regras de reescrita tenham que ser adicionadas, por exemplo, para trabalhar em posts paginados. Também pode precisar de mais algum trabalho para ter uma solução completa, por exemplo, ao excluir um cartoon-series delete também todos os episódios filhos? Adicionar um filtro na tela de edição de administrador para filtrar episódios por pai de postagem? Modifique o título dos episódios na tela de edição de administrador para mostrar o nome da série pai?

    
por cybmeta 14.03.2015 / 21:44
0

Não há necessidade de HARD-CODING neste caso ... Você pode simplesmente usar este plugin:

enlace

Você pode até pegar o código dele. No entanto, pode não ser uma solução completa.

    
por T.Todua 07.02.2017 / 09:29
-1

Você precisará escrever seu próprio código de análise de URL para isso, pois o wordpress precisa saber o tipo de postagem que ele tenta recuperar do banco de dados com base na estrutura de url e sua estrutura de URL não dá nenhuma dica para isso.

Isso não é algo muito fácil de fazer com a API de regras de reescrita do wordpress, mas não há nada que impeça você de ignorar o mecanismo de reconfiguração e analisar os URLs por si mesmo. Algo como 1. execute regras rewite wordpress. Se um conteúdo foi encontrado, exiba-o e saia 2. obter a primeira parte do URL, verifique se existe uma correspondência correspondente ao slug com o tipo de post esperado 3. loop no resto partes da URL verificar que as mensagens existem e estão no tipo certo. 4. Se tudo coincidir, mostre o último post encontrado, caso contrário, mostre uma página 404

    
por Mark Kaplun 14.03.2015 / 20:28