Uzyskiwanie hierarchicznych niestandardowych łączy typu post działa tak jak strony


16

Przekopałem się przez każde pytanie tutaj dotyczące permalinków niestandardowych typów postów, ale większość wydaje się być albo problemami z niestandardowymi przeróbkami taksonomii, albo oczywistym brakiem flush_rewrite_rules (). Ale w moim przypadku używam tylko niestandardowego typu postu (bez taksonomii), ustawionego na hierarchiczny (dzięki czemu mogę przypisywać relacje rodzic-dziecko), z odpowiednią „obsługą” atrybutów metabox itp. Itp. przepłukano przepisywanie przepisów na tysiąc różnych sposobów. Próbowałem różnych struktur permalink. Ale podrzędne adresy URL zawsze dają wynik 404!

Początkowo miałem niezależne niestandardowe typy postów dla elementów „nadrzędnych” i „podrzędnych” (przy użyciu p2p) i prawdopodobnie nie miałbym problemów z zastosowaniem taksonomii dla grupowania „rodzicielskiego” - wiem, że byłyby one semantycznie bardziej dokładne. Ale dla klienta najłatwiej jest im wizualizować hierarchię, gdy „posty” są wyświetlane w adminie tak jak strony: proste drzewo, w którym dzieci pojawiają się pod rodzicem, poprzedzone znakiem „-”, oraz w właściwe zamówienie. Można również zastosować różne metody przypisywania kolejności za pomocą przeciągania i upuszczania. Grupowanie według taksonomii (lub p2p) daje płaską listę „postów” na listach administratora, co po prostu nie jest tak wizualnie oczywiste.

Więc szukam dosłownie takiego samego zachowania jak podstawowe „strony”, ale z moim niestandardowym typem postu. Zarejestrowałem typ postu zgodnie z oczekiwaniami, a u administratora działa idealnie - mogę przypisać nadrzędnego i menu_order do każdego „postu” w biuletynie, pojawiają się one poprawnie na listach edycji:

Spring 2012
 First Article
 Second Article

A ich permalinki wydają się być poprawnie skonstruowane. W rzeczywistości, jeśli zmienię coś w strukturze, lub nawet zmienię podrożnik podczas rejestracji typu postu, automatycznie aktualizują się poprawnie, więc wiem, że coś działa:

http://mysite.com/parent-page/child-page/                  /* works for pages! */
http://mysite.com/post-type/parent-post/child-post/        /* should work? */
http://mysite.com/newsletter/spring-2012/                  /* works! */
http://mysite.com/newsletter/spring-2012/first-article/    /* 404 */
http://mysite.com/newsletter/spring-2012/second-article/   /* 404 */

Mam również standardowe podstawowe strony z utworzonymi relacjami hierarchicznymi, które wyglądają tak samo w adminie, ale w rzeczywistości działają również na interfejsie (zarówno adresy URL nadrzędny, jak i podrzędny działają dobrze).

Moja struktura bezpośredniego łącza jest ustawiona na:

http://mysite.com/%postname%/

Próbowałem również tego (tylko dlatego, że tak wiele innych odpowiedzi wskazywało na to, że jest potrzebna, chociaż w moim przypadku nie miało to sensu):

http://mysite.com/%category%/%postname%/

Moje rejestrowe argumenty CPT obejmują:

$args = array(
    'public'                => true,
    'publicly_queryable'    => true,
    'show_ui'               => true,
    'has_archive'           => 'newsletter',
    'hierarchical'          => true,
    'query_var'             => true,
    'supports'              => array( 'title', 'editor', 'thumbnail', 'page-attributes' ),
    'rewrite'               => array( 'slug' => 'newsletter', 'with_front' => false ),

Jedyną widoczną różnicą między moimi niestandardowymi elementami potomnymi typu posta a normalnymi stronami potomnymi strony jest to, że mój CPT ma ślimak na początku struktury permalink, a następnie ślimak nadrzędny / podrzędny (gdzie strony zaczynają się od ślimaka nadrzędnego / podrzędnego, bez „prefiksu”). Dlaczego to miałoby zepsuć, nie wiem. Wiele artykułów wydaje się wskazywać, że właśnie tak powinny zachowywać się takie hierarchiczne permalinki CPT - ale moje, choć ładnie uformowane, nie działają.

Co mnie też zaskakuje, kiedy sprawdzam zmienne query_vars dla tej strony 404 - wydają się zawierać prawidłowe wartości WP, aby „znaleźć” moje strony podrzędne, ale coś nie działa.

$wp_query object WP_Query {46}
public query_vars -> array (58)
'page' => integer 0
'newsletter' => string(25) "spring-2012/first-article"
'post_type' => string(10) "newsletter"
'name' => string(13) "first-article"
'error' => string(0) ""
'm' => integer 0
'p' => integer 0
'post_parent' => string(0) ""
'subpost' => string(0) ""
'subpost_id' => string(0) ""
'attachment' => string(0) ""
'attachment_id' => integer 0
'static' => string(0) ""
'pagename' => string(13) "first-article"
'page_id' => integer 0
[...]

Próbowałem tego z różnymi motywami, w tym dwadzieścia jeden, aby mieć pewność, że nie brakuje mi szablonu.

Korzystając z Insprite Rules Inspector, pojawia się to dla adresu URL: http://mysite.com/newsletter/spring-2012/first-article/

newsletter/(.+?)(/[0-9]+)?/?$   
       newsletter: spring-2012/first-article
           page: 
(.?.+?)(/[0-9]+)?/?$    
       pagename: newsletter/spring-2012/first-article
           page: 

jak jest wyświetlany na innej stronie inspektora:

RULE:
newsletter/(.+?)(/[0-9]+)?/?$
REWRITE:
index.php?newsletter=$matches[1]&page=$matches[2]
SOURCE:
newsletter

To wyjście przerobiłoby mnie do przekonania, że ​​zadziała następujący link „nie ładny”:

http://mysite.com/?newsletter=spring-2012&page=first-article

Nie 404, ale pokazuje „biuletyn” nadrzędnego elementu CPT, a nie dziecko. Żądanie wygląda następująco:

Array
(
    [page] => first-article
    [newsletter] => spring-2012
    [post_type] => newsletter
    [name] => spring-2012
)

Odpowiedzi:


15

To mój pierwszy raz, kiedy biorę udział w stosie wymiany, ale spróbuję i zobaczę, czy mogę pomóc ci wskazać właściwy kierunek.

Domyślnie hierarchiczne CPT zachowują się dokładnie tak, jak opisano. Unikalny przedrostek informacji o ślimaku, w tym przypadku „biuletyn”, informuje silnik przepisujący, jak rozróżniać żądania dotyczące różnych typów postów.

Te argumenty rejestracyjne CPT wyglądają dobrze, ale kiedy żądany jest CPT, pagenamezmienna zapytania nie powinna mieć wartości, a namezmienna zapytania powinna być taka sama jak newslettertutaj, więc wydaje się, że gdzieś w twoim konflikcie jest konflikt.

Aby pomóc w debugowaniu, zainstaluj i aktywuj wtyczkę Insprite Rules Inspector , a następnie odwiedź ekran w „ Narzędzia -> Przepisz reguły ”.

  1. Patrząc na listę, wszystkie reguły dotyczące biuletynu CPT powinny być wymienione przed wszelkimi regułami przepisywania strony. Sprawdź, czy tak jest, skanując kolumnę „ Źródło ”.
  2. Jeśli to się sprawdzi, wpisz adres URL swojego CPT „pierwszego artykułu” w polu „ Dopasuj adres URL ” i kliknij przycisk „Filtruj”, aby zobaczyć, która reguła jest zgodna. Powinien pasować do reguły biuletynu i reguły strony, ale reguła biuletynu powinna być pierwsza.

Jeśli to nie ujawni żadnych problemów, przeszukaj post_namekolumnę, wp_postsaby znaleźć inne posty ze ślimakiem „pierwszego artykułu”, aby sprawdzić, czy może dojść do kolizji. Wyszukaj również „biuletyn”, aby się upewnić.

Dodaj następujący fragment kodu, aby sprawdzić zmienne zapytania na początku żądania, aby sprawdzić, które z nich są ustawione przez dopasowanie reguły przepisywania (odwiedź potomny CPT na interfejsie użytkownika). Jeśli pagenamevar nie pojawia się tutaj, to jest ustawiany przez coś w dalszej części żądania:

add_filter( 'request', 'se77513_display_query_vars', 1 );

function se77513_display_query_vars( $query_vars ) {
    echo '<pre>' . print_r( $query_vars, true ) . '</pre>';

    return $query_vars;
}

Wszelkie wtyczki / funkcje modyfikujące zmienne zapytania mogą powodować konflikt, więc wyłącz je, jeśli nadal występują problemy. Opróżnij również reguły przepisywania po każdym kroku, szczególnie jeśli żądanie pasowało do niewłaściwej reguły w drugim kroku powyżej (zachowaj ekran „Permalinki” w osobnej zakładce i odśwież go).


Zredagowałem pytanie, aby wyświetlić wyniki inspektora reguł przepisywania, ponieważ te komentarze nie pozwalają na wystarczające formatowanie. Reguły CPT są wyświetlane na górze listy, zanim cokolwiek innego - ale nie jestem pewien, które z poniższych reguł są regułami „stronicowymi” (niejasne). Brak kolizji w post_namekolumnie.
somatyczne

masz jakieś przemyślenia na temat właściwej struktury permalink? Wróciłem do tego /%postname%/czasu, ponieważ włączenie /%category%/tylko zdaje się wprowadzać zamieszanie w inspektorze przepisywania. Widziałem nawet, jak ludzie twierdzą, że /%category%/jest magicznie odwzorowany na CPT, co oznacza „rodzic”, choć nie uważam tego za prawdę.
somatyczne

Wydaje się, że dane wyjściowe pochodzą z innej wtyczki, dlatego nie widzisz „źródła” reguły. Tak czy inaczej, wygląda na to, że reguła dobrze pasuje. Zredagowałem swoją odpowiedź, dodając fragment, aby sprawdzić zmienne zapytania we wcześniejszym żądaniu, aby upewnić się, że są ustawione poprawnie.
Brady Vercher

Jeśli chodzi o strukturę permalink, nie jestem fanem włączania tej kategorii. To tylko kolejna ruchoma część, która nic nie pomaga, a posty mogą należeć do wielu kategorii. Jeśli istnieje jakakolwiek szansa, że ​​możesz zmienić strukturę permalink w przyszłości lub chciałbyś, aby inny CPT ładował się bez prefiksu ślimaka, zaleciłbym „przestrzeń nazw” twojej struktury z czymś stałym i niepowtarzalnym /blog/%postname%/.
Brady Vercher

jest to właściwa wtyczka, ale istnieją dwie strony: „przepisz analizator” i „przepisz reguły”, obie oferujące testowy adres URL. Próbowałem na drugiej stronie i pokazało to źródło jako „program” dla pierwszej wciętej grupy i „stronę” dla drugiej.
somatyczny

5

parent/ChildPermalink działa po wyjęciu z pudełka tak długo, jak ustawić

'hierarchical'=> true,
'supports' => array('page-attributes' ....

Aktualizacja:

Właśnie przetestowałem go ponownie i działa zgodnie z oczekiwaniami, w tym przypadku testowym:

add_action('init','test_post_type_wpa77513');
function test_post_type_wpa77513(){
    $args = array(
        'public' => true,
        'publicly_queryable' => true,
        'show_ui' => true, 
        'show_in_menu' => true, 
        'query_var' => true,
        'rewrite' => true,
        'capability_type' => 'post',
        'has_archive' => true, 
        'hierarchical' => true,
        'supports' => array( 'title', 'editor', 'thumbnail', 'page-attributes' )
    ); 

    register_post_type( 'newsletter', $args );
}

i permalink ustawione na /%postname%/dostaję biuletyn / rodzic / dziecko działające dobrze.


mój powyższy kod tego nie pokazał, ale mam go page-attributesw podporach (co tak naprawdę polega tylko na pokazywaniu metaboksu do przypisywania pochodzenia, nie powinno to wpływać na permalinki) - ale na uzyskanie 404. Jaką strukturę permalink należy ustawić? czy to ma znaczenie?
somatyczny

@somatic właśnie przetestowałem go ponownie i działa dobrze, ponieważ w przypadku bezpośredniego łącza nie jestem pewien, czy powinno to mieć znaczenie, ale w jakikolwiek sposób zaktualizowałem swoją odpowiedź.
Bainternet,

Mogę potwierdzić, że dodając tablicę argumentów dla „etykiet” (bez których CPT nie pojawi się w adminie), ten podstawowy przykład działa na waniliowej instalacji WP3.5 z dwunastoma. Ale zauważam kilka kluczowych różnic w twoich register_post_type$ args: użyłem 'rewrite' => array( 'slug' => 'newsletter', 'with_front' => false )tam, gdzie właśnie użyłeś true. Ty też po prostu przeszedł truena has_archive, gdzie przeszedł pocisk. Jednak kiedy dopasowałem twoje argumenty, wciąż mam 404 ... Wciąż próbuję wyśledzić, gdzie się mylę.
somatic

3

Oprócz pytania »Czy próbowałeś go wyłączyć i włączyć ponownie?« , Muszę również zapytać: „Czy masz jakieś wtyczki aktywne i czy Twój motyw robi cokolwiek z linkami permalink (np. Rejestracja systematyki, typów postów, dodawanie reguł przepisywania? itp.)?

Jeśli tak: Czy nadal tak się dzieje po wyłączeniu wszystkich wtyczek i przełączeniu na TwentyEleven? wprowadź opis zdjęcia tutaj

Aby dalej debugować, przejdź do GitHub i pobierz wtyczkę Toschos „Rewrite” . Następnie przejdź do oficjalnego repozytorium wtyczek na wp.org i uruchom wtyczkę MonkeyManRewriteAnalyzer . Napisałem nawet małe rozszerzenie, żeby skleić oba trochę. To da ci wiele szczegółów na temat konfiguracji.


cóż, jeśli wszystko wyłączę , nie będę mieć niestandardowego typu postu, który jest celem tego pytania ... ale tak, próbowałem nawet z motywem dwadzieścia dwanaście. Nadal przeglądam kilka niezbędnych wtyczek, aby zobaczyć, co zakłóca zapytanie, ponieważ z tego, co widzę, same permalinki są dobrze uformowane.
somatyczny

@somatic Oczywiście nie wyłączam twojego :)
kaiser

@somatic Zobacz aktualizację.
kaiser

1

Więc po potwierdzeniu, że mogę uzyskać oczekiwane hierarchiczne zachowanie strony dzięki całkowicie czystej instalacji i tylko jednej deklaracji CPT, wiedziałem, że wina leży w mojej własnej wtyczce, której używam do obsługi tworzenia CPT (bardzo skomplikowana, obsługuje niestandardowe metaboksy, taksonomie) itp.). Problem polegał na tym, że pomimo wszystkich porad dotyczących sprawdzania, czy nie występują problemy z przepisywaniem lub zapytaniami, nie widziałem niczego oczywiście złego. Sprawdziłem każdy filtr i zaczep, przeglądając zapytanie w każdym punkcie i nie widząc niczego, co mogłoby spowodować 404.

Pozostało mi więc zadanie ręcznego wyłączenia / włączenia każdej z 9 dużych klas, a następnie znalezienia co najmniej 2 z nich powodujących 404, przejścia przez każdą funkcję jeden po drugim i wyłączenia / włączenia ich, a następnie śledzenia linii według linii w obrębie tych funkcji - brutalna próba zobaczenia, co spowodowało 404, nawet gdybym nie wiedział dlaczego.

Właśnie wtedy odkryłem, że korzystanie z niego jest konsekwencją $query->get_queried_object(). Wydaje się, że użycie tej funkcji otoki faktycznie modyfikuje samo zapytanie $, które, jak sądzę, zwracałem bez zmian na końcu mojej funkcji. Trzy filtry całej 2 klasy byli zaangażowani że zmodyfikowane zapytanie: parse_query, posts_orderby, posts_join- a wszystkie funkcje zwrotne wołały $query->get_queried_object()na przekazany $queryarg aby następnie przeprowadzić kilka testów warunkowych i czasami zmodyfikować zapytanie vars (jak dla szczególnych przypadkach zamówienia sort). O dziwo, te funkcje faktycznie działały dobrze, do czego zostały zaprojektowane, pomimo mojego użycia tej funkcji. Nigdy wcześniej nie zauważyłem niczego złego w zwróconym zapytaniu $!

Jakoś, po ponad roku rozwoju i użytkowania w dziesiątkach miejsc produkcji na żywo, nigdy nie doświadczyłem żadnych negatywnych skutków tego błędu. Tylko wtedy, gdy zapuściłem się w hierarchiczne CPT, ta jedna niewielka różnica nagle coś załamała. To część tego, co mnie tak mocno rzuciło - jak najlepiej mogłem powiedzieć, moje filtry zapytań były godne zaufania!

Przyznaję, że wciąż nie wiem dokładnie, dlaczego wywołanie tej funkcji łamie tylko ten jeden mały aspekt stron podrzędnych CPT - a jednak nigdy nie przejawiało żadnych innych problemów! Ale było jasne, że użycie go w wywołaniu zwrotnym filtra w $queryjakiś sposób zniekształciło zwracany element . Po usunięciu tego połączenia moje błędy 404 zniknęły.

Dzięki za wszystkie wskazówki - chciałbym podzielić nagrodę, ponieważ zyskałem wgląd w każdą odpowiedź, nawet jeśli ostateczne rozwiązanie było nieco niezwiązane. To była lekcja edukacyjna polegająca na tym, że nie ślepo ufasz swojemu kodowi, nawet jeśli działa on niezawodnie przez długi czas lub nie powoduje żadnych oczywistych błędów.

Czasami, ponieważ wykres Kaisera jest tak zgrabnie ucieleśniony, musisz po prostu zacząć rzucać przełącznikami, dopóki światła nie wrócą. W moim przypadku musiałem zastosować tę samą strategię rozwiązywania problemów aż do poszczególnych linii w funkcji, zanim zobaczyłem problem.


Możesz także użyć funkcji otoki get_queried_object()bez przechwytywania $wpdbobiektu.
kaiser

ale co $queryto chwyta? Używam tego obrębie filtru parse_query, a potrzeba specjalnie się poszukiwana przedmiot konkretnej $query, która jest przekazywana z filtrem ...
somatyczny

Właśnie próbowałem użyć opakowania w moim filtrze dla parse_query. Powodowało to ponownie te same błędy 404. Muszę znaleźć sposób na odtworzenie tego, co się get_queried_object()dzieje bez zanieczyszczania tych filtrów ...
somatyczny

-2

Czy używasz najnowszej wersji WP? Wydaje mi się, że to pierwsze pytanie (na przykład, gdy zadzwonisz do pomocy technicznej, a oni zapytają, czy komputer jest podłączony!), Ponieważ przeczytałem, że ten problem został rozwiązany w najnowszej aktualizacji wersji.

Na stronie digwp.com znajduje się post, który dotyczy tego problemu (http://digwp.com/2011/06/dont-use-postname/). Najwyraźniej WP nie może łatwo odróżnić postów i stron, a jeśli zaczniesz swoje adresy URL z opcją tekstową, WP wyzwala flagę, która tworzy regułę dla każdej strony / postu, którą masz. Jeśli masz dużo treści na swojej stronie, może to spowodować ogromną liczbę żądań, a Twój serwer prawdopodobnie przekroczy limit czasu, co spowoduje wiązkę 404, nawet jeśli strony tam są.

Więc. Jeśli najpierw użyjesz struktury opartej na liczbach, a następnie struktury opartej na tekście, założę się, że problem 404 zostanie rozwiązany. Teraz, biorąc pod uwagę problemy z SEO, nie użyłbym struktury dat, ale podjęcie takiej decyzji będzie dla ciebie wystarczająco logiczne.


2
Jestem na 3.5. Od wersji WP3.3.1 ten problem na digiwp został naprawiony.
somatyczne
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.