processException() v PRODUCTION modu s následným redirectem zlobí

Upozornění: Tohle vlákno je hodně staré a informace nemusí být platné pro současné Nette.
Petr Tvaroha
Člen | 25
+
0
-

Učím se pracovat s laděnkou a nemohu přijít na jednu věc. Zachytím výjimku a zpracuju jí pomocí processException($e), kdy si chci pouze zalogovat a emailovat chybu a pak chci pokračovat dál. Ale když pak volám $presenter->redirect(‚someview‘), tak dostanu další výjimku, která způsobí, že se zobrazí prázdná stránka, místo toho, aby skript pokračoval dál. Když nevolám redirect, tak to proběhne dle mých požadavků.

Je to vlastnost, nebo chyba?

Podrobněji:

  1. odešlu formulář
  2. data zpracuji v formSubmitted(), kde uložím data do DB a pak si chci poslat data mailem, ale nechci, aby uživatel zaregistroval, pokud by náhodou došlo k chybě při odeslání mailu:
<?php
//jsem ve třídě např. MyPresenter, mode mam nastaveny na PRODUCTION

public function formSubmitted()
{
	// zpracuju data, ulozim do DB
	...

	// chci je poslat v mailu, ale dojde k chybe pri odesilani
	try {
		$mail = new Mail();
		...
		$mail->send();
	} catch(Exception $e) {
		Debug::processException($e); // chci zalogovat do souboru a poslat si chybu emailem, což obojí proběhne v pořádku
	)
	// a ted chci normálně pokračovat, ale když uvedu ...
	$this->redirect('view2'); // tak dostanu další výjimku... (níže)
}

/* druhá výjimka:
PHP Fatal error:  Uncaught exception 'InvalidStateException' with message
'Cannot set HTTP code after HTTP headers have been sent
(output started at C:\Web\www\test\libs\Nette\Debug.templates\bluescreen.phtml:355).'
in C:\Web\www\test\libs\Nette\Web\HttpResponse.php:80
*/
?>

Předem díky za odpověď.

PHP 5.2.6 na Apache 2.0.63 na Win7, Nette 0.9.2 rev. b9fd602

Doplnění:

Právě jsem si stáhnul poslední dev verzi Nette, chová se stejně. Zajímavé je, že když volám v bootstrap.php:

<?php
Debug::enable(Debug::PRODUCTION, NULL, 'webmaster@example.com');
?>

chová se to tak, jak jsem popsal výše.

Pokud však přidám:

<?php
Environment::setMode('production',TRUE);
?>

Tak se mi zobrazí Error view: 500 Internal Server Error.

Editoval Petr Tvaroha (13. 12. 2009 14:32)

Honza Kuchař
Člen | 1662
+
0
-

Někde něco odesíláš na výstup. UTF-8 BOM mezeru nebo tak něco.

Petr Tvaroha
Člen | 25
+
0
-

Jo, jasně, že se tam něco posílá na výstup. Ale posílá to právě ta funkce processException(), která by ale neměla. Proto mi přijde, že v ní někde bude možná nějaká chybka.

redhead
Člen | 1313
+
0
-

Jen tak mimochodem, čí je ta funkce processException? Chybí ti tam ‚Debug::‘ ne?

Petr Tvaroha
Člen | 25
+
0
-

Ano, chybí tam Debug, opravil jsem to.

Petr Tvaroha
Člen | 25
+
0
-

Tak jsem zatím zjistil, že to je problém s output bufferingem, kdy se logují detaily výjimky do html souboru ve funkci Debug::processException().

Když zakomentuju…

ob_start(array(__CLASS__, '_writeFile'),1); 	// line 612, file Debug.php
self::_paintBlueScreen($exception);		// line 613
ob_end_flush();					// line 614

…tak to proběhne v pořádku.

Pro mě to tedy znamená, buď to nechat zakomentované a přijít o detaily výjimky, nebo si napsat vlastní funkci logException().

Wosonj
Člen | 36
+
0
-

ob_end_flush() ti pošle data na výstup, takže pak žádný redirect neuděláš. Na logování výjimek používáme tohle:

<?php
	ob_start();
	\Nette\Debug::_paintBlueScreen($exception);
	$content = ob_get_clean();
?>
Petr Tvaroha
Člen | 25
+
0
-

Díky moc! To mi dost pomůže.

Jenom ale potom nerozumím tomu, proč tedy Debug::processException() něco vůbec posílá na výstup, když mám $outputAllowed = FALSE. V popisu parametru je @param bool is writing to standard output buffer allowed? a já to tedy chápu tak, že by neměla funkce posílat na výstup vůbec nic, tiše provést vše potřebné (log, mail, …) a skončit.

Nebo to chápu špatně?