tags:

views:

41

answers:

2

In a PHP MVC framework, how can I cleanly and elegantly exit from the current controller/action, but continue normal script execution?

For example, let's say my framework normally follows this outline:

  1. Map URL to Controller/Action
  2. Instantiate Controller, call Action (capturing output)
    1. Do stuff
    2. Render View
    3. At end of Action method, continue normal operation
  3. Process output if necessary
  4. Send output to browser

Now, let's say I want to stop "normal" execution somewhere in the "Do Stuff" step to, say, render a different view, or do a header redirect, and I want to stop processing the rest of the body of the Action, but continue onto the "Process output" step

How can I achieve this the best way? My only ideas are:

//in controller
protected function redirect($url) {
    header("Location: $url");
    exit();
}

but this entirely skips the rest of the framework's execution, and dumps whatever was in the output buffer straight to the user. An alternative:

//in dispatcher
call_user_func_array(array($controller,$action),$params);
afterwards:
...

//in controller
protected function redirect($url) {
    header("Location: $url");
    goto afterwards;
}

However, this makes me twitch and goes against everything I've learned, especially because the label it's referencing is in another file completely.

So, is there any other way to achieve this?

Note: The redirect example probably should use the exit() way, because we're just redirecting to another page anyway and don't care about output. I'm looking for a general-use solution.

+1  A: 

In your Action method, you can collect all of your output in a string rather than printing it out. Print it out only at the end of the method. If you need to redirect or bail out, then you haven't output anything yet and you can either redirect or return from the method.

Scott Saunders
+1 for output buffering the Action.
LeguRi
+1  A: 

Perhaps you could write a custom exception to represent a "Stop normal execution in the 'Do Stuff'" step? It's messy... but it would work.

LeguRi
Wow, I hadn't thought of that! Granted, it kind of violates the idea of an exception, but it would bubble up until it hits a `catch(EarlyExitException)`, which I could wrap around my dispatch method...
Austin Hyde
Exactly... except for the whole "It violates the idea of an exception" as PHP does not yet have a `Throwable` interface.
LeguRi
Exceptions should be used for exceptional (error) circumstances. It sounds like "render a different view" is more of a flow control issues. If so, exceptions should not be used in "normal" conditions.
Keith Minkler
@Keith, I agree 120%, but with PHP as it is now, there is no other device that can "bubble" up through the call stack until you stop it. Until PHP has a `Throwable` interface that allows arbitrary objects to be thrown and caught, Exceptions are a uniquely powerful way of controlling flow. That being said, I will probably not implement this method. This is just an interesting use I have not thought of.
Austin Hyde