RuntimeException, Twig and Kohana
I use Twig with Kohana to do my templating, and came across a mental and really annoying error today.
I catch the exceptions thrown by the Request class (this is Ko 3.0.10 code) and depending on the environment, will either output or let them die quietly.
One of these catch-cases is if Twig can't find the template it's looking for. Well, it turns out there's a bug in Twig/PHP which allows for an uncatchable RuntimeException to sneak out.
See the following:
<?php
//
// If you're using Twig with Kohana, and setting up a way of catching Exceptions throw, you'll
// probably be doing something like this in your Bootstrap.php
//
try
{
$request = Request::instance();
$request->execute();
echo $request->send_headers()->response;
}
catch(Exception $e)
{
if($e instanceof RuntimeException)
{
echo 'Template Missing! ' . $e->getMessage();
exit();
}
...
}
//
// The above doesn't work! You need to do
//
try
{
$request = Request::instance();
$request->execute();
echo $request->send_headers()->response->render(); // Notice the render?
}
catch(Exception $e)
{
if($e instanceof RuntimeException)
{
echo 'Template Missing! ' . $e->getMessage();
exit();
}
...
}In the above, we have a simple try-catch pair, which detects the type of exception and dumps out a simple debug string.
If you do the first way, you'll get the uncatchable RuntimeException. This is because when you do "echo $request->response" you call the Kohana_Twig::__toString() function. And buried in the bowels of this function is a 'throw new RuntimeException'.
THIS DOESN'T WORK!
Usually if you try and throw an exception in __toString, PHP will yell at you. But somehow this function sidesteps it.
So to fix the problem, you need to call render() explicitly. This removes the __toString step and allows you to catch the Exception correctly.
So whose bug is it? Well, kinda both. Kohana Twig shouldn't throw an exception where it can occur in __toString. BUT, PHP should moan that you're doing it! So kinda both and kinda neither.
I won't tell you how blue the air turned when hunting for this one.