I would like to ask whether it's a good approach to redirect from within a model instead of a controller.
The reason I want to do that is because it is easier to unit test redirection from a model (I just pass a mock redirector object to the model in my tests) as opposed to controller which is more difficult to unit test. It also keeps controller thinner as all I do in the controller is create an instance of the model and pass it parameters from the request object. There is not a single if/else in the controller this way.
Is it a bad practise?
Most often in webapplications - MVC or not - redirects are implemented on a high-level layer. In non OOP code this often is a high level global function that knows a lot about the global static state and what represents a request and a response therein.
In more OOP driven sites, you find this often as a method with the "response" object (compare Symfony2 and HTTP Fundamentals; note that Symfony2 is not MVC), however, it often then has also some similar methods (e.g. see Difference between $this->render
and $this->redirect
Symfony2).
As most often those "response" objects are central in the web-application this qualifies as well as a high-level layer in my eyes.
From a testing standpoint - especially with integration testing - you normally do not need to test for redirects specifically. You should test that generally your redirect-functionality works on the HTTP layer so that parts of your application that make use of it can rely on it. Common problems are to not really follow the suggestions given in the HTTP/1.1 specs like providing a response body with redirects. A well working webapplication should honor that. Same for using fully qualified URIs.
So how does all fit this into MVC here? In a HTTP context this could be simplified as the following:
forward
directly - that is executing a different command, the client would not be used for that, the redirect not necessary (sub-command).This pretty much sounds like that the actual redirect is just some output you send to the client on the protocol level in client communication. It belongs into the interface of that protocol you want to support. So not into the model but into the client-interface and the boundary of the client interface inside an MVC application is the controller AFAIK.
So the redirect probably is a view-value-object with a special meaning. To get that working in a HTTP MVC you need a full URL abstraction which most PHP frameworks and libraries make a big round around because it's not well known how that works. So in the end I'd say: Do as Symfony2 has done, place it in a high level layer component, drop MVC and live with the deficiencies.
Everything else is hard to achieve, if you try otherwise, there is high risk to not stop with abstracting anymore.
Neither controller nor model should be redirecting anything anywhere. HTTP Location header is form of a response, which strictly in purview of views.
Model layer deals with business logic, it should be completely oblivious even to the existence of presentation layer.
Basically, it goes down to this: controllers handle input, views handle output. HTTP headers are part of output.
Note: when dealing with Rails clones, it is common to see redirects performed in "controller". It is because what they call "controller" is actually a merger of view and a controller responsibilities. This is a side-effect of opting to replace real views with simple templates as the 3rd side of triad.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With