Natknąłem się na dziwny problem.
Załóżmy, że masz dostęp do losowego adresu URL o głębokości co najmniej trzech poziomów:
http://example.com/a/b/c
http://example.com/a/b/c/d
...
To is_404()
jest true
. Na razie w porządku. Ale z jakiegoś powodu sprawdzane są ostatnie posty.
$wp_query->request
jest
SELECT SQL_CALC_FOUND_ROWS wp_posts.ID
FROM wp_posts
WHERE 1=1
AND wp_posts.post_type = 'post'
AND (
wp_posts.post_status = 'publish'
OR wp_posts.post_status = 'private'
)
ORDER BY wp_posts.post_date DESC
LIMIT 0, 5
Który wtedy oczywiście have_posts()
powraca true
i tak dalej. Czy ktoś może to wyjaśnić?
Co do tej pory się dowiedziałem:
Powodem, dla którego uruchamia się tylko na trzech lub więcej poziomach głębokości, jest to, że wcześniej WP szuka postów i załączników, które w jakiś sposób skutkują jakimś innym zachowaniem.
Wygląda na to, że chociaż WP rozpoznaje żądanie jako 404 w pewnym momencie, pobiera najnowsze posty. Z pomocą @kaiser i @GM wyśledziłem to gdzieś z /wp-includes/class-wp.php:608
Odpowiedzi:
Możesz być zaskoczony, ale nie ma w tym nic dziwnego.
Przede wszystkim wyjaśnijmy, że w WordPress, gdy odwiedzasz frontendowy URL, wywołujesz zapytanie. Zawsze.
To zapytanie jest tylko standardem
WP_Query
, podobnie jak te uruchamiane przez:Jest tylko jedna różnica:
$args
zmienne są generowane przez WordPress przy użyciuWP::parse_request()
metody. Metoda ta polega tylko na sprawdzeniu adresu URL i reguł przepisywania oraz przekonwertowaniu adresu URL na tablicę argumentów.Ale co się stanie, gdy ta metoda nie będzie w stanie tego zrobić, ponieważ adres URL jest nieprawidłowy? Argument zapytania jest po prostu taką tablicą:
(Źródło tutaj i tutaj ).
Tak więc tablica jest przekazywana do
WP_Query
.Teraz spróbuj zrobić:
Czy jesteś zaskoczony, że zapytanie jest dokładnie tym w OP? Nie jestem.
Więc,
parse_request()
buduje tablicę z kluczem błęduWP_Query
, która po prostu ją uruchamiahandle_404()
uruchamiany po zapytaniu, sprawdza'error'
parametr i ustawia wartośćis_404()
trueTak,
have_post()
iis_404()
nie są powiązane. Problem polega na tym, żeWP_Query
nie ma systemu do zwarcia zapytania, gdy coś pójdzie nie tak, więc po zbudowaniu obiektu przekaż mu kilka argumentów, a zapytanie zostanie uruchomione ...Edytować:
Istnieją 2 sposoby rozwiązania tego problemu:
404.php
szablon; WordPress załaduje to na 404 adresy URL i tam nie musisz sprawdzaćhave_posts()
Wymuś
$wp_query
pustkę na 404, coś w stylu:źródło
$wp->matched_rule
), ale zapytanie wciąż przechodzi przez ruchy, ponieważ nie zwraca na to uwagi.WHERE 1=0
w sql, ponieważ nie może zatrzymać zapytania, więc wymuś zapytanie, które nic nie zwraca ... @Rarstis_404()
kontrolę.