Anyway, now there is some news to publish. I've transferred the site to another server and set the code to run on top of PHP 5.3 (FINALLY). There might still be some bugs lying around, so please be forgiveful.
I'm currently working in developing an exiting new service for one of our beloved customers. This means that I have my hands in the clay, so to say, and hopefully be able to whip up some technical stuff in a blog form soon.
BRB :)
]]>Let's take a look what a typical application does. The Action Controller recieves the request, reads data from the Request object, validates parameters and passes the validated data to the Model. Data read from the Model is then forwarded to the View layer. The request might have came anywhere, from an HTML form, Javascript function, RSS reader etc. The controller also manages the program flow by manipulating the Request object and in many examples also performing HTTP redirects (using the Redirector Action Helper).
The View layer is the part of the MVC framework that determines how the data is pushed to the Response object. It pulls the data from the view variables and outputs them to the requesting user in the way the user expects it. Using the ContextSwitch Action Helper, the application can automatically select the right view script for the type of the data it needs to render. So whether we're packing the Response with HTML, JSON or XML data, it is done in the View script.
The Controller does not need to know how the call to the requested action was made - it just needs to do its thing and let the View layer handle the rest.
An HTTP redirect is done by manipulating the Response object, which IMHO should be done in the View layer. The Action Controller controls the program flow within the dispatch loop by manipulating the Request object and should not bother itself with View related things. This leads to stronger separation of the Controller and View components.
In some cases it is practical that the same Action Controller can accept requests from several "clients", for example a Javascript component located on your page, a dedicated form or a client using a RESTful interface. I use a login feature as an example, you might want that your site has:
In this case, whenever a form is posted, you'd probably check that the credentials are correct and then log the user in. The tricky part begins here: if the user came via form, you'd probably want to redirect him to the page they came from. The AJAX call does not need redirecting, so you'd need to provide the calling JS function some information on how the login process went in a JSON string.
This gets a bit difficult if you have implemented your redirection in the Controller layer, since you need first to determine where the call came from (Zend_Controller_Request_Http::isXmlHttpRequest()) and then act accordingly (forward or return JSON). To accomplish this you would either put an if..else to your authentication action or just write two separate Controllers.
We'll use the available tools to solve the problem described above. The ContextSwitch Action Helper provides a way of selecting the correct view script automatically based on the context of which the action was called. This enables us to remove the if...else control statement and subsequent redirection from the controller. The controller is now only responsible for logging in the user, writing the results of the process in the view variables and rendering the selected view script.
The view script for Ajax requests checks from the view variables, if the log in was a success and renders a JSON response.
The view script for our traditional form based log in passes the status information to the flashMessenger helper (yes, I am well aware it is an action helper - I'm just calling it from the view layer) and then does the redirect. On the forwarded page, the user is presented the login status message.
Since the View layer does not have any tools for manipulating flashMessenger or redirecting the user, I implemented view helper proxy classes for both.
The separation explained above has several benefits:
If using the Redirector Action Helper, you should also mind the fact that the default functionality is to exit after setting the Location header. This interrupts the program flow, because the exit is forced and no plugin hooks get executed (postDispatch, dispatchLoopShutdown etc).
The idea mentioned here is not the only solution to the problem, I am pretty certain that there are other ways to accomplish the same. Regarding the example provided, it probably is possible to send both the HTTP Location header and the JSON payload in the same request and let the front end code just ignore the header, or just do add an http-equiv metatag to the document.
]]>
It's half past twelve in the morning. I have work tomorrow and I really shouldn't be doing this right now.
But still, I feel pride in my heart to finally be able to go into "production" with this never-ending project of mine. This website has been my passion from the day I registered my domain six years ago, but as with so many passions, it took control over me and I was not able to deliver what I promised to myself.
Countless of CMS's, several static pages and lot of tears were created before what you see now emerged. This site is actually not running on some content management system (although there are some good ones, not made by me :D, available) but a semi-static site running on top of Zend Framework.
This is my playground for tech stuff. I hope to be dutiful enough to keep the content up to date, to post blog entries and to follow and support the development of my favourite framework by testing new features on this site.
Feel free to browse the source code and comment. I know that everything is yet not perfect there and lot of things need refactoring and cleaning, but I hope to get some support from my random visitors :)
Thanks&bye
mkoh
]]>
Kommentit
Ei kommentteja, mikset kirjoittaisi ensimmäistä?