Benutzerdefinierter Posttyp von Wordpress 3.3 mit /% postname% / permastruct?

9

Es gibt einen früheren Beitrag mit ähnlichem Titel, der jedoch nicht in WordPress 3.3 enthalten ist. Dies ist wichtig, da 3.3 interessanterweise Werbung macht: "Verwenden Sie die Permalink-Struktur für den Nachnamen ohne Leistungseinbußen."

Das Problem mit Wordpress 3.2 und früheren Versionen war, dass zuerst die Seitennamen und dann 404 angezeigt wurden. Die willkürlichen Beitragstypen wurden nicht zuerst überprüft. 3.3 hingegen muss nach Beitragstypen, dann nach Seiten und schließlich nach 404 suchen (da dies für diese Funktion wirbt). Dies impliziert, dass benutzerdefinierte Beitragstypen ohne Slug einfach sein sollten , wenn sie nicht post_type=postirgendwo hart codiert haben.

Ich kann jedoch noch keine 3.3-spezifische Lösung finden.

Frage : Wie kann ich die Permalink-Struktur "/% postname% /" für einen bestimmten benutzerdefinierten Beitragstyp "xyz" definieren?

Vielen Dank.

Ciantic
quelle
Ich sehe keine Frage - was fragst du eigentlich?
Travis Northcutt
Aus Gründen der Übersichtlichkeit möchten Sie einen neuen benutzerdefinierten Beitragstyp definieren, der die Permalink-Struktur von /% postname% /? Verwendet. Planen Sie, dass Posts dieselbe Permastruktur verwenden, oder haben sie ein Präfix?
Prettyboymp
Im Anschluss daran, um zu sehen, ob jemand eine Antwort findet. Ich habe auch die oben genannten Ansätze ausprobiert und einfach den Umschreib-Slug auf '/' gesetzt, wodurch auch Seitenpermalinks unterbrochen werden. Le

Antworten:

2

Dies ist in WP 3.3 nicht einfach möglich, es sei denn, Sie täuschen die Umschreiberegeln so vor, dass sie an der richtigen Stelle sind, und lassen wp_rewrite glauben, dass im Frontend ausführliche Regeln verwendet werden. Die folgende Klasse funktioniert.

class Test_Post_Type {
    const POST_TYPE = 'test';

    public static function init() {
        global $wp_rewrite;

        $post_type_obj = register_post_type( self::POST_TYPE, array(
            'labels' => array(
                'name' => __( 'Tests' ),
                'singular_name' => __( 'Test' ),
                'add_new' => __( 'Add New' ),
                'add_new_item' => __( 'Add New Test' ),
                'edit_item' => __( 'Edit Test' ),
                'new_item' => __( 'New Test' ),
                'all_items' => __( 'All Tests' ),
                'view_item' => __( 'View Test' ),
                'search_items' => __( 'Search Tests' ),
                'not_found' => __( 'No Tests found' ),
                'not_found_in_trash' => __( 'No Tests found in Trash' ),
                'menu_name' => __( 'Tests' )
            ),
            'publicly_queryable' => true,
            'exclude_from_search' => true,
            'hierarchical' => false,
            'public' => true,
            'rewrite' => false,
            'has_archive' => true,
            'supports' => array( 'title', 'editor', 'thumbnail', 'test_source' ),
            'taxonomies' => array( 'category', 'post_tag' ),
        ) );

        $post_type_obj = get_post_type_object(self::POST_TYPE);

        //register the rewrite tag for permalink building
        $wp_rewrite->add_rewrite_tag( '%' . $post_type_obj->query_var . '%', '([^/]+)', $post_type_obj->query_var . '=' );

        //we have to add the permastruct here in order to build the permalink, otherwise we'll need to filter the post_type link
        add_permastruct(self::POST_TYPE, '%' . $post_type_obj->query_var . '%/', false );

        //add a filter to remove the permastructs generated above
        add_filter(self::POST_TYPE . '_rewrite_rules', array(__CLASS__, '_remove_default_rules')); 

        //now we add a filter to put the generated rewrite rules in the correct spot
        add_action('generate_rewrite_rules', array(__CLASS__, '_filter_rewrite_rules'));

        if(!is_admin()) {
            //we need verbose_page_rules to be on on the front end in order for pages to be process properly
            $wp_rewrite->use_verbose_page_rules = true;
        }
    }

    /**
     * Filter to remove the rules for this post type when they're automatically generated due to the permastruct registration
     * @param type $rules
     * @return type 
     */
    public static function _remove_default_rules($rules) {
        return array();
    }

    /**
     * Filters the rules at the end to add back the ones for this post type at the bottom
     * @param WP_Rewrite $wp_rewrite 
     */
    public static function _filter_rewrite_rules($wp_rewrite) {
        $post_type_obj = get_post_type_object(self::POST_TYPE);
        $my_rules = $wp_rewrite->generate_rewrite_rules('%' . $post_type_obj->query_var . '%', EP_NONE);
        $wp_rewrite->rules += $my_rules;
    }

}

add_action( 'init', array( 'Test_Post_Type', 'init' ) );
Prettyboymp
quelle
Durch Kopieren wurde dieser Code in mein Thema eingefügt und die Umschreiberegeln wurden gelöscht. Ein neuer Beitrag wurde hinzugefügt, der Beitrag wurde angezeigt (URL ist korrekt) und 404 ... auf WP 3.3.1. Irgendeine Idee, warum das bei mir nicht funktioniert? (Danke übrigens für den Code!)
Rob Vermeer
EP_NONE -> EP_PERMALINK, damit Kommentarseiten funktionieren und mehrere Beitragstypen mit /% postname% / funktionieren, müssen Sie auch den Filter parse_query verwenden. Siehe meine Antwort oben.
Ciantic
Rob, hast du einen neuen Beitrag hinzugefügt oder einen neuen 'Test'-Beitrag hinzugefügt? Dies war in der ursprünglichen Frage nicht klar, ob Posts auch die Permastruktur von /% post_name% / haben müssen. Wenn dies der Fall ist, warum überhaupt einen neuen Beitragstyp erstellen? Außerdem treten möglicherweise Probleme mit Namenskonflikten auf, wenn mehr als ein Beitragstyp dieselbe Permastruktur aufweist.
Prettyboymp
1

Heilige Autoschlüssel!

Ich denke das funktioniert . Es funktioniert fast, es ist super einfach, nur eine Zeile:

global $wp_rewrite;
$args = array(
    'public' => true,
    'publicly_queryable' => true,
    'show_ui' => true,
    'show_in_menu' => true,
    'query_var' => true,
    'rewrite' => array('slug' => 'anything'),
    'capability_type' => 'post',
    'has_archive' => true,
    'hierarchical' => false,
    'menu_position' => null,
    'supports' => array('title','editor','thumbnail')
);
register_post_type('my_custom_post_type', $args);

$wp_rewrite->add_permastruct('my_custom_post_type', "%my_custom_post_type%");

PS Wenn Sie dies zu Hause versuchen, nachdem Sie diese eine Zeile hinzugefügt haben, gehen Sie zu "Einstellungen" -> "Permalinks" und speichern Sie die Änderungen, um die Permalinks zu aktualisieren.

Ich habe den WP- register_post_type()Quellcode gelesen und eine Zeile gefunden:

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

Unnötig zu sagen, aber ohne Schnecke kam ich zu dem Schluss, dass es funktionieren sollte, und das tat es auch . Auch die Permalink-Bearbeitung unter dem Titel im Editor funktioniert einwandfrei!

Update: Dadurch werden Seitenpermalinks unterbrochen, zurück zum Zeichenbrett ...

Ciantic
quelle
Ich habe es auch mit einem ähnlichen Ergebnis versucht. Wäre sehr cool wenn das klappen würde. Vielleicht jemand anderes mit einer Idee?
Rob Vermeer
@RobVermeer Es wurde festgestellt, dass WordPress ohne die Zeile (nur mit dem Standard-Slug) bereits in der Lage ist, zur URL umzuleiten. ZB "Some-Post" leitet zu "irgendetwas / Some-Post" weiter. In Codespeak gibt es irgendwo im Code eine Unterstützung für CPTs ohne Slug, die standardmäßig nur umgeleitet werden. Gesichtspalme
Ciantic
1

Die Antwort von Prettyboymp ist fast dieselbe, die ich gestern erhalten habe, aber ich bin nicht zufrieden damit. Die Antwort von prettyboymp hat einen Fehler. Sie funktioniert nicht, wenn /% postname% / gleichzeitig für mehrere Beitragstypen verwendet wird.

Hier ist meine Antwort, die sich auch mit der aktuellen Struktur befasst und eine Reihe von Beitragstypen erstellt, auf die zurückgegriffen werden kann. Es gibt jedoch auch einen Fehler, wenn zwei Beitragstypen denselben Slug haben und beide /% postname% / sind, dann werden beide angezeigt.

class MyCustomPostType {
    /**
     * Register post type
     **/
    public static function register_post_type() {
        global $wp_rewrite;

        $args = array(
            'public' => true,
            'publicly_queryable' => true,
            'show_ui' => true,
            'show_in_menu' => true,
            'query_var' => true,
            'rewrite' => false,
            'capability_type' => 'post',
            'has_archive' => true,
            'hierarchical' => false,
            'menu_position' => null,
            'supports' => array('title','editor','thumbnail')
        );

        register_post_type('my_custom_post_type', $args);

        // Enables the pages to work simultaneously
        $wp_rewrite->use_verbose_page_rules = true;
        add_filter("rewrite_rules_array", array(__CLASS__, 'rewrite_rules_array'));
        add_action("parse_query", array(__CLASS__, 'parse_query'));
        add_filter("post_type_link", array(__CLASS__, 'post_type_link'), 1, 4);
    }

    public static function post_type_link($link, $post, $leavename=false, $sample=false) {
        if ($sample && ($begin = strpos($link, "?my_custom_post_type=")) !== false) {
            return substr($link, 0, $begin-1) . "/%my_custom_post_type%/";
        }
        return str_replace("?my_custom_post_type=", "", $link) . "/";
    }

    public static function parse_query($query) {
        global $wp, $wp_rewrite;

        // Is this query for /%post_name%/? Is it main request query?
        if (isset($query->query['name'])
            && substr($wp->matched_rule, 0, 7) == "([^/]+)"
            && isset($query->query)
            && isset($wp->query_vars)
            && $query->query == $wp->query_vars)
        {
            //echo '<p><h1>hit!</h1></p>';
            if (!($post_types = get_query_var("post_type"))) {
                if ($wp_rewrite->permalink_structure == "/%postname%/")
                    $post_types = array("post");
                else
                    $post_types = array();
            }

            if (is_array($post_types))
                $post_types[] = "my_custom_post_type";

            set_query_var("post_type", $post_types);
            //set_query_var("posts_per_page", 1);
        }
    }

    public static function rewrite_rules_array($array) {
        global $wp_rewrite;
        // Same rules as in /%post_name%/
        return array_merge($array, $wp_rewrite->generate_rewrite_rules("/%postname%/", EP_PERMALINK));
    }
}


add_action('init', array("MyCustomPostType", "register_post_type"));
Ciantic
quelle
Ist es möglich, dass bestimmte Post-Typen hierarchisch werden? Ich habe es selbst versucht, aber nichts scheint zu funktionieren ... Es glaubt, der Beitrag ist ein Anhang mit Eltern / Kind / ... Und wenn ich Eltern / Kind / Enkelkind mache / bekommt er eine 404.
Rob Vermeer
1

Ich habe eine Lösung erstellt und konnte kein Problem damit finden. Bitte versuchen Sie es mir zu sagen, wenn Sie ein Problem finden

add_action('init', 'firmasite_resimlitarif_cpt', 0);
function firmasite_resimlitarif_cpt() 
{

// Yemek Tarifi

  $args = array(
    'public' => true,
    'show_in_menu' => true, 
    'permalink_epmask' => EP_NONE,
    'rewrite' => array('slug'=>'/','with_front'=>false),
    'has_archive' => false,
    'supports' => array('title','editor','thumbnail')
  ); 
  register_post_type('yemek',$args);

}


// http://wordpress.stackexchange.com/questions/37650/wordpress-3-3-custom-post-type-with-postname-permastruct
add_action("parse_query", 'firmasite_resimlitarif_parse_query');
function firmasite_resimlitarif_parse_query($query) {
    global $wp, $wp_rewrite;


    // Is this query for /%post_name%/? Is it main request query?
    if (isset($query->query['name'])
        && substr($wp->matched_rule, 0, 7) == "([^/]+)"
        && isset($query->query)
        && isset($wp->query_vars)
        && $query->query == $wp->query_vars)
    {
        if (!($post_types = get_query_var("post_type"))) {
            if ($wp_rewrite->permalink_structure == "/%postname%/")
                $post_types = array("post");
            else
                $post_types = array();
        }

        if (is_array($post_types)){ 
            $post_types[] = 'yemek';
            $post_types[] = 'page';
        }


        set_query_var("post_type", $post_types);
    } 
}

Ändern Sie 'yemek' mit Ihrem Beitragstypnamen.

Ünsal Korkmaz
quelle
0

Die sauberste Antwort, die ich dafür finden könnte (ich baue ein Plugin auf, das wirklich einen benutzerdefinierten Beitragstyp ohne führenden Slug benötigt), ist die Verwendung einer benutzerdefinierten Seitenvorlage anstelle eines benutzerdefinierten Beitragstyps.

Auf diese Weise kann Ihr "benutzerdefinierter Beitragstyp" URLs wie / was auch immer enthalten, ohne sich Gedanken über das Betreten einer Seite oder das Posten von Permalinks machen zu müssen.

Um dies zu tun, habe ich Folgendes getan:

  • Hinzufügen einer benutzerdefinierten Seitenvorlage in meinem Plugin
  • Einrichten der Seitenvorlage, damit sie im Seiteneditor ausgewählt werden kann
  • Erstellen von benutzerdefinierten Meta-Feldern, die nur für meine Seitenvorlage angezeigt werden

Dies erlaubte mir:

Die Nachteile

Obwohl dies nicht auf Seiten- oder Post-Links stampft, hat es natürlich einige offensichtliche Nachteile.

Kein Archiv Sie haben kein Archiv (wenn Sie dies möchten). Dies kann jedoch gelöst werden, indem Sie eine weitere Seitenvorlage erstellen, um mit Ihrer benutzerdefinierten Vorlage ein Archiv aller Seiten zu zeichnen.

Verwaltet unter Seiten Im Administrator wird nicht die nette Navigation für die linke Hand angezeigt, mit der alle Beitragstypen zusammengefasst werden.

Dies könnte teilweise gelöst werden, indem der Seitenliste ein Filter hinzugefügt wird (damit Sie nach der verwendeten Seitenvorlage filtern können), der in einer neuen Spalte verwendete Seitenvorlage anzeigt usw.


Davon abgesehen wollte ich etwas, das die Benutzer nicht dazu bringt, sich zu fragen, warum sie eine neue benutzerdefinierte Seite erstellt haben, und festgestellt hat, dass sie entweder keine normalen Seiten mehr erreichen können oder dass die neue benutzerdefinierte Seite dazu führt, dass eine vorhandene Seite auf ihrer Website verschwindet.

Ich weiß, dass es keine echte Lösung ist, aber es ist eine Alternative, die sich hervorragend für meine Bedürfnisse eignet.

Freibeuter
quelle