Cómo establecer una relación padre-hijo entre diferentes tipos de publicaciones personalizadas

10

Acabo de configurar una relación de publicación / padre entre un tipo de publicación "episodios" y un tipo de publicación "serie de dibujos animados".

Utilicé este bit de código para agregar en el cuadro de meta para asignar el padre de otro tipo de publicación:

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.
}

Eso funcionó en la pantalla de administración al permitirme configurar la serie como padre para el episodio, pero cuando intento ver la publicación, obtengo un 404. La estructura de la URL es:

domain/episodes/series-name/episode-name

La url para la serie es:

domain/cartoon-series/series-name

Me gustaría que la url del episodio fuera:

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

¿Qué me estoy perdiendo? ¿Es posible hacer que un tipo de publicación completo sea el hijo de otro tipo de publicación? Entonces, incluso podría obtener la url para la lista de episodios:

domain/cartoon-series/series-name/episodes

Gracias! Matt

Según lo solicitado, aquí está el código para los dos tipos de publicaciones personalizadas en cuestión:

$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 );

Estoy usando el plugin CPT UI, así que no puedo editar ese código directamente. Ese es el código de exportación que proporciona la IU de CPT.

No tengo ningún otro código que vincule los dos CPT. Tal vez eso es lo que me estoy perdiendo. Acabo de encontrar ese código en línea que coloca el metabox en la página para hacer el enlace. ¿No es suficiente hacer el trabajo? Parece que establece el post_parent.

Gracias! Matt

    
pregunta Mattaton 13.03.2015 - 23:20

3 respuestas

8

Finalmente he encontrado una solución de trabajo. La serie de dibujos animados se puede registrar como lo hizo, pero los episodios de tipos de publicación personalizados no pueden ser jerárquicos (creo que WordPress espera que el contenido principal sea del mismo tipo que el contenido secundario si la relación se establece con post_parent en la tabla de base de datos wp_posts ).

Al registrar episodios, la regla de reescritura debe establecerse en el slug que desea, que es cartoon-series/%series_name% . Luego, podemos filtrar el enlace de episodios para reemplazar %series_name% con el nombre real del tipo de publicación padre cartoon-series y una regla de reescritura para decirle a WordPress cuando se solicita un tipo de publicación de serie de dibujos animados y cuándo es un episodio.

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 );

NOTA : recuerde vaciar las reglas de reescritura después de guardar el código anterior y antes de intentarlo. Vaya a wp-admin/options-permalink.php y haga clic en guardar para registrar las reglas de reescritura.

NOTA 2 : es probable que haya que agregar más reglas de reescritura, por ejemplo, para trabajar con publicaciones paginadas. También puede necesitar más trabajo para tener una solución completa, por ejemplo, al eliminar un cartoon-series ¿eliminar también todos los episodios secundarios? ¿Agregar un filtro en la pantalla de edición de administración para filtrar los episodios por mensaje principal? ¿Modificar el título de los episodios en la pantalla de edición de administración para mostrar el nombre de la serie principal?

    
respondido por el cybmeta 14.03.2015 - 21:44
0

No hay necesidad de HARD-CODING en este caso ... Simplemente puede usar este complemento:

enlace

Incluso puedes tomar código de él. Sin embargo, puede que no sea una solución completa.

    
respondido por el T.Todua 07.02.2017 - 09:29
-1

Necesitará escribir su propio código de análisis de URL para eso, ya que wordpress necesita saber el tipo de publicación que intenta recuperar de la base de datos en función de la estructura de URL y su estructura de URL no le dará ninguna pista para esto.

Esto no es algo que sea muy fácil de hacer con la API de reglas de reescritura de wordpress, pero no hay nada que le impida omitir el mecanismo de reescritura y analizar las URL por su cuenta. Algo como 1. ejecutar WordPress reglas rewite. Si se encontró un contenido, visualícelo y salga 2. obtener la primera parte de la url, verifique si hay una publicación que coincida con esa bala con el tipo de publicación esperado 3. haga un bucle en las partes restantes de la URL para verificar que las publicaciones existen y están en el tipo correcto. 4. Si todas las coincidencias muestran la última publicación encontrada, de lo contrario, visualice una página 404

    
respondido por el Mark Kaplun 14.03.2015 - 20:28

Lea otras preguntas en las etiquetas