Apache 2.4.10 за Windows. Имам стабилно приложение за Zend Framework 1 PHP. Току-що реших да добавя ErrorDocument
директива към .htaccess
. Напълно съм объркан от трите различни поведения, които получавам с 404-те, в зависимост от начина, по който те се задействат.
Моят .htaccess файл съдържа:
ErrorDocument 404 'Page not found' RedirectMatch 404 /uploads/(.*/)?private/
Ако просто напиша url за несъществуваща страница в адресната лента, получавам страницата за грешка, създадена от Zend Framework's ErrorController
.
Ако вляза /uploads/private/foo
(съвпадение на RedirectMatch
), тогава получавам ErrorDocument
продукция, както се очаква.
Но ако в моя PHP код го правя
http_response_code(404); exit(0);
след това получавам стандартната страница за грешка в браузъра. Това е, което тотално не успявам да разбера. Ако използвам раздела Мрежа в инструментите за разработчици на Chrome, виждам, че и трите заявки дават статус 404. Предполагам, че мога да си представя, че настройката за обработка на грешки на Zend Framework би задържала несъществуващия url и ще направи своето, заобикаляйки ErrorDocument
обработка. Но не разбирам как веднага exit
от PHP код със статус 404 ще премине ErrorDocument
.
Какъв PHP код мога да напиша, за да задействам ErrorDocument
директива?
РЕДАКТИРАНЕ:
Въз основа на отговора от Тим Фонтан, трябва да дам повече контекст: Както бе отбелязано по-горе, моят ZF ErrorController
страницата е настроена да изглежда така, както аз искам - виждам тази страница, когато въвеждам URL за несъществуваща страница. В конкретната ситуация всъщност изпълнявам код от WordPress mu-plugin
(WP е инсталиран под ZF public
директория). The .htaccess
файлът естествено не насочва заявки за съществуващи файлове по-долу public
към ZF. Искания за всичко по-долу public/wp
вместо това отидете на public/wp/index.php
The mu-plugin
bootstraps ZF (но не извиква bootstrap's run()
метод) и след това разглежда заявката. Ако това не е разрешено (според променливите на сесията Auth на ZF), искам да дам 404 (не 403). Преди това направих това, като всъщност пренасочих към несъществуващ URL адрес и това показа ErrorController
страницата е добре - но също така остави адресната лента, показваща несъществуващия URL адрес. Реших да добавя ErrorDocument
директива, така че адресната лента все пак да показва URL адреса, въведен от потребителя. В моя действителен код нямах прост низ в директивата, а по-скоро този URL: /default/error/error?error_handler[type]=404
. Промених го на обикновен низ, само за да се уверя, че няма нещо в URL адреса, който причинява проблем. Имайте предвид, че когато въвеждам URL за нещо в private
директория, задействаща RedirectMatch
, Виждам ZF ErrorController
страница, така че знам, че URL адресът сам по себе си не е проблем. Просто исках да намаля сложността на тази публикация.
Отговорът на Тим казва, че кодът ми за проблем изпраща празна страница 404 директно в браузъра и браузърът я променя на обяснителен текст. Явно това се случва!
Означава ли това, че проблемът ми е, че трябва да създам малко съдържание и употреба на страницата с нулева дължина header()
за да зададете състоянието, защото http_response_code()
изпраща празно съдържание директно в браузъра? Но това, което е неясно в отговора му, е защо ErrorDocument
директива ще бъде заобиколена.
URL адресът на заявката, причиняващ това поведение, е http://www.example.com/wp/foo
. The DocumentRoot
е .../public
. Това не се пренаписва от .htaccess
да отидете на ZF, но отива директно на public/wp/index.php
. В този случай бих си помислил, че ErrorDocument
ще бъде задействано ...
РЕДАКТИРАНЕ 2:
Или изчакайте, може би точката на Тим всъщност не е свързана с обработката на ZF Error, но че от гледна точка на Apache, входящата заявка е удовлетворена (като отидете на public/wp/index.php
и изпълнява PHP), така че зависи от PHP кода да се справи, не мога да се върна към Apache ErrorDocument
след това! Предполагам, че имах наистина основно неразбиране как работи ErrorDocument. Трябва да намеря някакъв начин да извикам ErrorController
код директно за показване на страницата, която искам със статус 404! Дъ!
Предполагам, че ще приема отговора на Тим, макар че ако иска да изясни / обобщи своето мнение за това кога ErrorDocument
обработката влиза в игра, това би било хубаво :-)
РЕДАКТИРАНЕ 3:
Само за да приключа това. Приех отговора на Тим, защото той разкри основното ми неразбиране как апачите ErrorDocument
директива работи. Но това не ми показа директно как да разреша проблема, който изпитвах, като открих, че искам да върна статус 404, използвайки страницата ми за персонализирано състояние на Zend Framework, но бях в заявка на WordPress, след като стартирах ZF, без да стартирам Приложението MVC, работещо под bootstrap. Нямах опит да се забърквам с предния контролер на ZF, но след като рових малко в документите, измислих това решение, което има точно същия ефект като пълния ErrorDocument
директива исках да се препъна.
$error_url = $this->serverUrl() . '/default/error/error?error_handler[type]=404'; $request = new Zend_Controller_Request_Http($error_url); $front = Zend_Controller_Front::getInstance(); $front->returnResponse(true); $response = $front->dispatch($request); $response->setRawHeader('HTTP/1.1 404 Not Found'); $response->sendResponse(); exit(0);
Вероятно във вашите правила за htaccess имате и правило за пренаписване, за да насочвате всички заявки към Zend Framework. На този етап Apache (и ErrorDocument) всъщност не е на снимката, тъй като сте му казали, че искате заявките да се обработват от PHP.
Когато го направите:
http_response_code(404); exit(0);
изпращате празна страница 404 на браузъра. Много браузъри са настроени да показват собствени 404 страници, ако размерът на 404 страницата, която получават от сървъра, е по-малък от X байта. (Само за по-добро потребителско изживяване.)
Zend Framework трябва да хване това и да използва собствена страница за грешка в зависимост от това където поставяте този PHP код (и вероятно въз основа на някои опции за конфигуриране).
Предлагам ви да актуализирате страницата Zend Framework ErrorController, за да изглеждате както искате. Не вярвам, че има начин за ръчно обработване на заявката обратно към Apache (както беше).