Festlegen der Eltern-Kind-Beziehung zwischen verschiedenen benutzerdefinierten Beitragstypen

14

Ich habe gerade eine Beziehung zwischen einem Beitragstyp "Folgen" und einem Beitragstyp "Zeichentrickserie" eingerichtet.

Ich habe dieses Code-Bit verwendet, um es in das Meta-Feld einzufügen und das übergeordnete Element eines anderen Beitragstyps zuzuweisen:

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

Auf dem Administratorbildschirm konnte ich die Serie als übergeordnetes Element für die Episode festlegen. Wenn ich jedoch versuche, den Beitrag anzuzeigen, erhalte ich den Wert 404. Die URL-Struktur lautet:

domain/episodes/series-name/episode-name

Die URL für die Serie lautet:

domain/cartoon-series/series-name

Ich möchte, dass die URL für die Folge lautet:

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

Was vermisse ich? Ist es möglich, einen ganzen Beitragstyp zum Kind eines anderen Beitragstyps zu machen? Dann könnte ich sogar die URL für die Episodenliste erhalten:

domain/cartoon-series/series-name/episodes

Vielen Dank! Matt


Wie gewünscht, ist hier der Code für die beiden fraglichen benutzerdefinierten Beitragstypen:

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

Ich verwende das CPT-UI-Plugin, daher kann ich diesen Code nicht direkt bearbeiten. Dies ist nur der Exportcode, den die CPT-Benutzeroberfläche bereitstellt.

Ich habe keinen anderen Code, der die beiden CPTs verbindet. Vielleicht fehlt mir das ja. Ich habe gerade den Code online gefunden, der die Metabox auf der Seite platziert, um die Verknüpfung herzustellen. Reicht es nicht aus, die Arbeit zu erledigen? Sieht so aus, als würde post_parent gesetzt.

Vielen Dank! Matt

Mattaton
quelle
Es tut mir leid, aber ich habe mich geirrt. Die Eltern-Kind-Beziehung ist korrekt eingestellt. Die Meta-Box verwendet kein Meta-Feld (das hat mich beim ersten Mal verwirrt), verwendet parent_idQuery Var und benötigt keinen weiteren Code, um die Beziehung festzulegen. Das Problem ist, dass die generierte URL von WordPress nicht erkannt wird. Ich habe versucht, eine Umschreiberegel zu finden , die funktioniert, aber ich hatte keinen Erfolg. Ich suche jetzt nach einer Lösung.
Cybmeta
Nach einigen Nachforschungen glaube ich, dass Sie es nicht so zum Laufen bringen können, wie Sie es möchten. Es scheint nicht möglich zu sein, einen Beitragstyp als übergeordnetes Element eines anderen Beitragstyps zu haben. Nun, es ist möglich, dass mit Ihrem Code diese Beziehung tatsächlich festgelegt ist, aber wenn Sie sehen, dass der untergeordnete Beitrag im Frontend nicht funktioniert. Ich habe versucht, Regeln umzuschreiben und pre_get_postsdie Abfrage ohne Erfolg zu ändern. Es handelt sich um etwas Komplizierteres, das ich nicht verstehen konnte. Als ob eine Katze Eltern eines Hundes wäre. Ich empfehle, nur einen hierarchischen Beitragstyp zu verwenden oder die Beziehung mithilfe von Metafeldern festzulegen .
Cybmeta
Ich denke, dass ein hirarchischer Beitragstyp perfekt zu Ihrer Situation passt.
Cybmeta
2
Ich versuche wirklich, damit NICHT kompliziert zu werden. Wenn es eine elegantere Lösung gibt, bin ich ganz Ohr. Ich bin im Allgemeinen neu bei WP und habe es bisher ziemlich gut gemacht, aber dieser hat mich überrumpelt. Normalerweise würde ich die Zeichentrickserie einfach zu einer Kategorie machen und der Episode zuweisen. Das Problem ist, ich habe auch andere verschachtelte Daten als Episoden, die unter die Zeichentrickserie fallen. Es scheint also, als müsste eine Zeichentrickserie auch ein CPT sein. Es ist kompliziert! :-D Kannst du mir erklären, was du mit nur einem hierarchischen Beitragstyp meinst?
Mattaton

Antworten:

9

Endlich habe ich eine funktionierende Lösung gefunden. Die Zeichentrickserie kann wie Sie registriert werden, aber die benutzerdefinierten Beitragstypen der Episoden können nicht hirarchisch sein (ich denke, WordPress erwartet, dass übergeordneter Inhalt dem untergeordneten Inhalt entspricht, wenn die Beziehung post_parentin der wp_postsDatenbanktabelle festgelegt wird).

Bei der Registrierung von Episoden muss die Umschreiberegel auf den gewünschten Slug eingestellt werden cartoon-series/%series_name%. Dann können wir den Episoden-Link filtern, um ihn %series_name%durch den tatsächlichen Namen des übergeordneten cartoon-seriesPost-Typs zu ersetzen, und eine Umschreiberegel festlegen, die WordPress mitteilt, wann ein Post-Typ für eine Zeichentrickserie angefordert wird und wann eine Episode ist.

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

HINWEIS : Denken Sie daran, die Umschreiberegeln nach dem Speichern des obigen Codes und vor dem Testen zu löschen. Gehen Sie zu wp-admin/options-permalink.phpund klicken Sie auf Speichern, um die Umschreiberegeln neu zu erstellen.

HINWEIS 2 : Möglicherweise müssen mehr Umschreiberegeln hinzugefügt werden, um beispielsweise für paginierte Posts zu funktionieren. Auch kann es etwas mehr Arbeit erfordern, um eine vollständige Lösung zu haben, zum Beispiel beim Löschen eines cartoon-seriesLöschvorgangs auch alle Kinderepisoden? Einen Filter im Admin-Bearbeitungsbildschirm hinzufügen, um Episoden nach übergeordneten Elementen zu filtern? Ändern Sie den Episodentitel im Admin-Bearbeitungsbildschirm, um den Namen der übergeordneten Serie anzuzeigen.

cybmeta
quelle
Danke, dass Sie sich das angeschaut haben! Es scheint, dass der von Ihnen veröffentlichte Code den Namen der Zeichentrickserie aus der URL entfernt. Anstatt% series_name% durch den Namen der Episode zu ersetzen, sollte% series_name% der Name des übergeordneten Elements der Episode sein. Der Episodenname wäre danach. Aus irgendeinem Grund wird das Feld Zeichentrickserie nicht ausgefüllt, damit ich einen Elternteil auswählen kann. Deshalb dachte ich, Episoden müssten hierarchisch sein. Ich versuche herauszufinden warum.
Mattaton
Ja, Episoden müssen hierarchisch sein, damit die Meta-Box der Cartoon-Serie ausgefüllt wird.
Mattaton
Bei hierarchischen Episoden, damit ich die übergeordneten Elemente festlegen kann, wurde die URL nur noch schlechter. Mit der Schnecke, wie Sie vorgeschlagen haben, erhalte ich den Seriennamen zweimal in der URL. Also, anstatt domain/episodes/series-name/episode-namewie zuvor, bekam ichdomain/episodes/series-name/series-name/episode-name
Mattaton
Wie gesagt, Episoden können nicht hierarchisch sein. Ich habe den Meta-Box-Code so geändert, dass er mit nicht hierarchischen Beitragstypen gefüllt ist. Verwenden Sie den genauen Code, den ich gepostet habe, den ich getestet habe und der funktioniert. Wenn Sie einen anderen Code verwenden, kann ich nicht wissen, was falsch ist. Kopieren Sie einfach den Code aus der Antwort und testen Sie ihn. Möglicherweise müssen Sie das CPT-UI-Plugin deaktivieren oder zumindest die benutzerdefinierten Beitragstypen aus dem Plugin löschen, sobald sie im Code registriert sind.
Cybmeta
Ah, ich entschuldige mich, ich hatte schnell gescannt und dachte, dass dieser Teil derselbe sei. Sie haben Recht, die Seite wird jetzt geladen und die URL sieht korrekt aus.
Mattaton
1

In diesem Fall ist HARD-CODING nicht erforderlich. Sie können einfach dieses Plugin verwenden:

https://wordpress.org/plugins/add-hierarchy-parent-to-post/

Sie können sogar Code daraus holen. Möglicherweise handelt es sich jedoch nicht um eine vollständige Lösung.

T.Todua
quelle
-1

Sie müssen dafür Ihren eigenen URL-Parsing-Code schreiben, da WordPress den Typ des Posts kennen muss, den es basierend auf der URL-Struktur aus der Datenbank abzurufen versucht, und Ihre URL-Struktur keinen Hinweis darauf gibt.

Dies ist nicht sehr einfach mit der API für das Umschreiben von Regeln von WordPress zu tun, aber es gibt nichts, was Sie daran hindert, den Umschreibemechanismus zu umgehen und die URLs selbst zu analysieren. So etwas wie 1. WordPress ReWite-Regeln ausführen. Wenn ein Inhalt gefunden wurde, zeigen Sie ihn an und beenden Sie 2. Rufen Sie den ersten Teil der URL ab, und überprüfen Sie, ob ein Beitrag vorhanden ist, der dem erwarteten Beitragstyp entspricht im richtigen Typ. 4. Wenn alles passt, wird der zuletzt gefundene Beitrag angezeigt, andernfalls wird eine 404-Seite angezeigt

Mark Kaplun
quelle