Vlastní ErrorPresenter pro modul v Nette 2.2
- jEhLa
- Člen | 70
Dobrý den,
v aplikaci mám dva moduly (Front a Admin). Chci si pro modul Front nastavit
vlastní ErrorPresenter, ale modul Admin zatím používal výchozí Nette
ErrorPresenter.
Když nastavím v neonu errorPresenter: 'Front:Error'
, tak se
použije ve všech modulech.
Našel jsem návody jak to nastavit ve starších verzích Nette přímo
v metodě startup()
BasePresenteru pro konkrétní modul, přes
$this->getApplication()->errorPresenter
, ale tato metoda je
již označena jako deprecated.
Zkoušel jsem toto vyřešit tím že jsem si v BasePresenteru injectnul
Nette\Application\Application
a zkoušel mu nastavit
errorPresenter. Toto však také nefungovalo a stále se volal výchozí
ErrorPresenter.
Asi je to tím, že se aplikace k presenteru ještě ani nedostala, protože v routeru provádím dotaz do DB na zjištění presenteru. A již zde může nastat chyba, že presenter nebyl nalezen.
Jak nato? Nedá se již nastavit více ErrorPresenterů pro různé moduly přímo v neonu?
- Jan Tvrdík
- Nette guru | 2595
Error presenter musí být vždy jenom jeden, ale uvnitř něho můžeš forwardnout (interně přesměrovat) na jiný error presenter.
use Nette\Application\UI;
use Nette\Application\Request as AppRequest;
class ErrorPresenter extends UI\Presenter
{
public function renderDefault(\Exception $exception, AppRequest $request)
{
if (Strings::startsWith($request->presenterName, 'Front:')) {
$this->forward(':Front:Error:', [
'exception' => $exception,
'request' => $request,
]);
}
...
}
}
- Tomáš Kolinger
- Člen | 136
Ne, jde mít jen jeden error presenter.
Detekoval modul je problém, hlavně pokud nastane chyba před/při zavolání presenteru.
Nejednodušší je mít klasicky jeden presenter a teprve tam se rozhodovat
co zobrazit, mít prostě sadu pohledů jak pro frontend, tak backend (např.
backend_404.latte
, frontend_500.latte
, …). Co
zobrazit můžeš detekovat podle URL, pokud backend routy prefixuješ pomocí
admin/, tak ti stačí vytáhnout z requestu URL a kouknout na začátek.
Jednoduché, rychlé a jisté.
- Jan Tvrdík
- Nette guru | 2595
Nette ho automaticky předává, viz https://github.com/…lication.php#L170
- Jan Tvrdík
- Nette guru | 2595
A jsi si jist, že proběhl ten předchozí požadavek? Nenastala chyba
třeba už při routování? Případně jak vypadá
$this->parameters
?
- Jan Suchánek
- Člen | 404
Router:
/**
* @return \Nette\Application\IRouter
*/
public function createRouter()
{
$router = new RouteList();
$backRoutes = new RouteList('Back');
$route = new Route('admin/<presenter>[/<action>[/<id>]]', array(
'presenter' => 'Default',
'action' => 'default',
'id' => NULL,
));
$backRoutes[] = $route;
$frontRoutes = new RouteList('Front');
$route = new Route('[<lang [cs|en|de]{2} >/]<presenter>[/<action>][/<id [0-9]+>]', array(
'presenter' => 'Default',
'action' => 'default',
'lang' => 'cs',
'id' => NULL,
));
$frontRoutes[] = $route;
$router[] = $backRoutes;
$router[] = $frontRoutes;
return $router;
}
dump $this->parameters v ErrorPresenteru
array (2)
exception => Nette\Application\BadRequestException #f578
defaultCode protected => 404
message protected => "Cannot load presenter 'Front:Aaa', class 'App\FrontModule\Presenters\AaaPresenter' was not found in '/Users/example/Sites/test/app/FrontModu ... " (182)
string private => ""
code protected => 404
file protected => "/Users/example/Sites/test/vendor/nette/application/src/Application/Application.php" (92)
line protected => 128
trace private => array (2)
0 => array (6) [ ... ] 1 => array (6) [ ... ]
previous private => Nette\Application\InvalidPresenterException #97cc
xdebug_message => "Nette\Application\InvalidPresenterException: Cannot load presenter 'Front:Aaa', class 'App\FrontModule\Presenters\AaaPresenter' was not found in '/Us ... " (1640)
request => NULL
Editoval jenicek (12. 6. 2014 11:42)
- Šaman
- Člen | 2667
Teď to zkouším a když se presenter nenajde, tak je v objektu application
nastavený request na NULL. Jediný, kdo může v takovém případě
rozhodnout, který ErrorPresenter použít, je IMHO router podle toho, která
routa se matchne.
Je docela mrzuté, že tenhle problém nemá rozumné řešení. Aspoň
předpokládám, že řešení
od @enumag trpí stejným neduhem, protože ten request se získává ze
stejného objektu (Application).
Běžně tohle nepotřebuji, ale teď řeším modul pro exporty, který komunikuje přes API a má vracet JSON. A v něm bych rád vracel i všechny chyby, které nastanou, pokud se matchne routa toho modulu.
- Šaman
- Člen | 2667
Místo navrhovaného requestu z parametru mi funguje vytáhnout si HttpRequest přímo z presenteru. Jen se asi nepozná, jesli zachytávám chybu v modulu Export, nebo v presenteru ExportPresenter na frontendu.
<?php
public function renderDefault($exception)
{
# ExportModule
$relativeUrl = Strings::lower($this->getHttpRequest()->getUrl()->getRelativeUrl());
if ( $relativeUrl === 'export' || Strings::startsWith($relativeUrl, 'export/') ) {
# já tu třeba posílám JsonResponse
}
# původní kód
}
?>
Editoval Šaman (3. 5. 2015 1:37)
- the_ress
- Člen | 1
Pro případy, kdy se presenter nenajde, jsem použila toto:
if ($request === null){ // When presenter doesn't exist, but we can still get a match
$request = $this->context->router->match($this->getHttpRequest());
}
if ($request && Nette\Utils\Strings::startsWith($request->presenterName, 'Admin:')){
...
Route vypadá nějak takto:
/admin/<presenter=default>[/<action=default>]