Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

HttpNotFoundException in ViewModel #1019

Closed
kusmierz opened this issue Jun 14, 2012 · 3 comments
Closed

HttpNotFoundException in ViewModel #1019

kusmierz opened this issue Jun 14, 2012 · 3 comments

Comments

@kusmierz
Copy link

throwing HttpNotFoundException in ViewModel shows me "standard" 404 page, nevertheless I've the 404 route. It has been catched in ViewModel::__toString() method. Than Error::exception_handler() is calling HttpNotFoundException::handle(), which is in fact (because of extend) is HttpException::handle()... calling overloaded method HttpNotFoundException::response().

Ok, and here we have:

return new \Response(\View::forge('404'), 404);

Fine. First of all, look at index.php. By default it's (after try-catch block... which is trying to catch HttpNotFoundException but ViewModel has lazy render() method, so it can't be catched there!):

// This will add the execution time and memory usage to the output.
// Comment this out if you don't use it.
$bm = Profiler::app_total();
$response->body(
    str_replace(
        array('{exec_time}', '{mem_usage}'),
        array(round($bm[0], 4), round($bm[1] / pow(1024, 2), 3)),
        $response->body()
    )
);

$response->send(true);

The exception is throwing on str_replace(.., .., $response->body()) because it's calling silently __toString (see above). First of all I have some problems with Profiler (it shows sometimes even two times in code - at the beginning and at the end!). Secondly... HttpNotFoundException::response() is sending status 404 header, but after that we have $response->send(true);, and $response has 200 status header, so webbrowser get "OK, Everything fine mate!". Bad.

Next, I'm trying to show my page. I discovered, that \View::forge('404') is looking for 404.php view file in app/views folder. So I put there something like this:

<?php

$route = array_key_exists('_404_', Router::$routes) ? Router::$routes['_404_']->translation : Config::get('routes._404_');

$response = new \Response(\ViewModel::forge($route), 404);
$response->send(true);

plus I've added $this->request()->response()->set_status(404); in my 404's ViewModel::view() method.

Still really badly but besides it works. I can't forward to call Controller (ie. $response = Request::forge($route)->execute()->response();), 'cause it's creating neverending loop. Uh.

So in short, my question is, how to catch HttpNotFoundException exception from ViewModel class?

@WanWizard
Copy link
Member

I'm closing this as won't fix.

Reason behind it is that when you're in the Viewmodel, you're already busy with the V part of MVC, sending output to the client. All control decisions should have been made by then, that's what the controller is for.

This sounds like you have a design issue in your application.

@kusmierz
Copy link
Author

Hm, as in Documentation:

A ViewModel shouldn't do any data manipulation but can contain database calls and any other retrieval or preparation operations needed to generate the View's data.

Ok, so in your mind, firstly I should check in controller if I can get entry, and if it exists, get again same data from database (second query at least!) to show in ViewModel. Ok, but a little bit redundant...

@WanWizard
Copy link
Member

No, that's not what I said (or meant).

The data for the view should be passed to it (or to its viewmodel) from the controller (which has used model calls to get it). The idea behind this statement is that you can fetch ancillary data in the viewmodel. Like stuff for dropdowns, info about the logged-in user, etc. Info that is needed in the view but has nothing to do with the controllers function.

If you fetch important / required data in the viewmodel, you're basically doing data manupulation, which may lead to a result what warrants alternation of the request flow. And that should be handled in the controller.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants