Wordpress 3.3 niestandardowy typ postu z /% postname% / permastruct?

9

Istnieje wcześniejszy post o podobnym tytule, ale nie zagląda on do WordPressa 3.3, co jest ważne, ponieważ 3.3 reklamuje się ciekawie: „Używaj struktury bezpośredniego łącza do nazwy bez ograniczenia wydajności”

Problem z Wordpress 3.2 i wcześniejszymi polegał na tym, że najpierw przeglądał nazwy stron, a następnie 404. Najpierw nie sprawdzał arbitralnych typów postów. 3.3 z drugiej strony muszą wyglądać typy postów, potem strony, a na koniec 404 (ponieważ reklamuje tę funkcję). To sugeruje, że niestandardowe typy postów bez ślimaka powinny być proste , jeśli post_type=postgdzieś nie kodują .

Nie mogę jednak znaleźć rozwiązania specyficznego dla 3.3.

Pytanie : Jak mogę zdefiniować permalink struct "/% postname% /" dla dowolnego niestandardowego typu postu "xyz"?

Dzięki.

Ciantic
źródło
Nie widzę pytania - o co właściwie pytasz?
Travis Northcutt
Dla jasności chcesz zdefiniować nowy niestandardowy typ postu, który korzysta ze struktury łącza bezpośredniego w /% postname% /? Czy planujesz, aby posty również używały tej samej permastruktury, czy będą miały prefiks?
prettyboymp
Następnie sprawdź, czy ktoś wymyśli odpowiedź. Próbowałem również powyższych podejść wraz z prostym ustawieniem ślimaka przepisywania na „/”, który również przerywa permalinki stron. Le

Odpowiedzi:

2

W WP 3.3 nie jest to łatwe, chyba że oszukasz reguł przepisywania w odpowiednim miejscu i sprawisz, że wp_rewrite sądzi, że w interfejsie używane są pełne reguły. Poniższa klasa działa.

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
źródło
Skopiuj wklej ten kod do mnie, opróżnij reguły przepisywania. Dodano nowy post, przeglądałem post (adres URL jest poprawny), otrzymałem 404 ... Na WP 3.3.1. Wiesz, dlaczego to nie zadziała? (Dzięki za kod btw!)
Rob Vermeer
EP_NONE -> EP_PERMALINK, aby strony komentarzy działały, a następnie, aby uzyskać wiele typów postów pracujących z /% postname% /, musisz również użyć filtru parse_query. Zobacz moją odpowiedź powyżej.
Ciantic
Rob, dodałeś nowy post czy dodałeś nowy post? Testowy? Nie było jasne w pierwotnym pytaniu, czy posty muszą mieć również strukturę permastracyjną /% post_name% /. Jeśli tak, to po co nawet tworzyć nowy typ postu? Ponadto będziesz mieć potencjalne problemy z konfliktami nazw, jeśli więcej niż jeden typ postów ma tę samą strukturę permastyczną.
prettyboymp
1

Święte kluczyki do samochodu!

Myślę, że to działa . To prawie działa, jest bardzo proste, tylko jedna linia:

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 Jeśli spróbujesz tego w domu, po dodaniu tej jednej linii Idź do „Ustawienia” -> „Permalinks” i zapisz zmiany, odświeży permalinki.

Czytałem register_post_type()kod źródłowy WP i znalazłem wiersz:

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

Nie trzeba dodawać, ale bez ślimaka doszedłem do wniosku, że powinno działać i tak się stało . Nawet edycja bezpośredniego linku pod tytułem w edytorze działa poprawnie!

Aktualizacja: To przerywa bezpośrednie linki do strony, powrót do tablicy kreślarskiej ...

Ciantic
źródło
Próbowałem też tego, z podobnym skutkiem. Byłoby bardzo fajnie, gdyby to zadziałało. Może ktoś z pomysłem?
Rob Vermeer
@RobVermeer Zauważył, że bez wiersza (z domyślnym ślimakiem) WordPress może już przekierowywać na adres URL. Np. „Jakiś post” przekierowuje na „cokolwiek / jakiś post”. W codespeak, gdzieś w kodzie jest wsparcie dla CPT bez ślimaka, po prostu domyślnie przekierowuje. twarz dłoń
Ciantic
1

odpowiedź prettyboymp jest prawie taka sama, jak wczoraj, ale nie jestem z tego zadowolona. Odpowiedź prettyboymp ma jedną wadę, nie działa, gdy /% postname% / jest używany jednocześnie na wielu typach postów.

Oto moja odpowiedź, która również analizuje bieżącą strukturę i tworzy tablicę typów postów, na których można cofnąć. Jest w tym także jedna wada, jeśli dwa typy postów mają ten sam ślimak i oba są /% postname% /, to pokazuje oba.

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
źródło
Czy to możliwe, że niektóre typy postów są hierarchiczne. Sam tego próbowałem, ale wydaje się, że nic nie działa ... Wydaje się, że post jest załącznikiem do rodzica / dziecka / ... A jeśli ja zrobię rodzic / dziecko / wnuka / dostanie 404.
Rob Vermeer
1

Stworzyłem rozwiązanie i nie mogłem znaleźć z nim problemu. Spróbuj mi powiedzieć, jeśli znajdziesz problem

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

Zmień „jemek” za pomocą nazwy typu posta.

Ünsal Korkmaz
źródło
0

Najczystszą odpowiedzią, jaką mogłem wymyślić (buduję wtyczkę, która naprawdę potrzebuje niestandardowego typu postu bez żadnych dodatkowych informacji) jest użycie niestandardowego szablonu strony zamiast niestandardowego typu posta.

W ten sposób Twój „niestandardowy typ postu” może mieć adresy URL takie jak / cokolwiek, bez konieczności martwienia się o wchodzenie na strony lub bezpośrednie linki do postów.

Aby to zrobić, skończyło się na tym, że:

  • Dodanie niestandardowego szablonu strony wewnątrz mojej wtyczki
  • Konfigurowanie szablonu strony, aby można go było wybrać w edytorze stron
  • Tworzenie niestandardowych pól meta, które pojawiają się tylko dla mojego szablonu strony

To pozwoliło mi na:

Wady

Oczywiście, chociaż nie tupie to na linkach do stron lub postów, ma kilka oczywistych wad.

Brak archiwum Nie będziesz mieć archiwum (jeśli chcesz), ale można to rozwiązać, tworząc inny szablon strony, aby narysować archiwum wszystkich stron przy użyciu niestandardowego szablonu.

Zarządzane w ramach stron Nie masz przyjemnej nawigacji po lewej stronie administratora, która grupuje wszystkie typy postów razem.

Można to częściowo rozwiązać, dodając filtr do listy stron (aby umożliwić filtrowanie według używanego szablonu strony), pokazując dowolny szablon strony użyty w nowej kolumnie itp.


Biorąc to pod uwagę, chciałem czegoś, co nie sprawi, że użytkownicy będą się zastanawiać, dlaczego utworzyli nową stronę niestandardową i stwierdzili, że albo nie mogą już dotrzeć do normalnych stron, albo nowa strona niestandardowa spowodowała zniknięcie istniejącej strony w ich witrynie.

Wiem, że to nie jest prawdziwe rozwiązanie, ale jest to alternatywa, która zadziałała doskonale na moje potrzeby.

Kaper
źródło