I've searched around but there doesn't seem to be a clear consensus on which one is better. Currently, all the HTML forms on the site point to a single PHP file. Each form has a hidden input specifying the action (e.g. 'user-login', 'user-logout'), and the PHP file calls methods from that.
So my question is: Should I point each form back to itself, related forms to a single file or all forms to a single file? And in terms of MVC, should processing take place in the controller or form?
Should I point each form back to itself, related forms to a single file or all forms to a single file?
You should point everything to index.php, which then delegates other components (controllers in MVC terms) to take care of the processing. The controller will then decide which view it wants to render. index.php would be in this case something we call the front controller. (note: below I am recommending ZF1 as a learning platform. ZF1 has a "front controller" class. Some people may argue that THAT one is the front controller and index.php is what they call the entry script. In my opinion, that is only the second "front" controller. Nevertheless, both opinions are controversed, so make your own opinion).
And in terms of MVC, should processing take place in the controller or form?
In terms of OOP first and foremost: the object is the only one who knows how to validate its own data (the principle of self-containment), so the form should validate itself. If it's about a model, the model should be called by either the controller, or the form - it's a matter of taste. No matter which way, the same principle applies: you feed the Model with data and call its validation method.
As you may have noticed, the Form class is a Model.
Don't let yourself fooled by the hype called MVC. Respect the OOP principles above all.
Regarding MVC: the MVC pattern says: the controller only coordonates the other components, for instance it takes the input, creates a Form instance, and calls the Form's validation method.
I advise you to use a framework to better see how all these pieces work together. The best would be zend framework 1, which has little to do with real life requirements, BUT which is a masterpiece in terms of patterns and practices.
Maybe ZF2 will change that mistake with the extra front controller.
Looking at the other answers, I feel the need to clarify some terminology used in my answer:
Model is a model. There's plenty of documentation about MVC
Form is a subclass of Model. It takes care of the validation. It may also have a method Form::__toString() which renders the HTML form in the view (the V in MVC)
view is the html file, and it's rendered under the supervision of the controller (C in MVC)
To recap, the overall execution flow would look like this:
<form action ...
entry script (a front controller)
router (it decides which Controller to forward the request to)
the Controller coordinates all the actions, calling the Model::validate() of one or many models (including Form, which is also a Model)
in the end, the Controller choses to render() a view (a html file), which could contain a call to Form::__toString(), in which case the Form is a hybrid of Model and "renderer".
Fun
Profit
That's it, basically. Different frameworks have different data/execution flow. ZF1's looks like this for instance: http://www.slideshare.net/polleywong/zend-framework-dispatch-workflow
In MVC terms your processing should take place in the controller. You shouldn't have any processing logic in your form (the view). Whether you have a different controller for each form is up to you. You could, for example, have a single controller that accepts all form submissions and performs some common processing (such as csrf detection) and then invokes your other controllers for each form. Alternatively, you could have a single controller that loads validation requirements from a database and behaves differently depending on which form has been submitted.
In MVC terms, making all form point to a single script means you've got a Front-Controller for Forms. There is one controller that deals with form requests.
Should I point each form back to itself, related forms to a single file or all forms to a single file?
That depends on your needs and the design maybe even architecture of your site.
And in terms of MVC, should processing take place in the controller or form?
Processing in MVC normally takes place within the controllers (lightly only) and the models (heavy processing). So if you're looking for an exemplary MVC design implementation you most probably will have Form Models that are used by the Controller(s).
This will ensure that you can make use of forms more flexible and you don't duplicate code for form processing within your application.
In my opinion you should use one file for each purpose. Same as mvc structure, this is a good approach for programming and it will be helpfull when your code gets really complicated.
You question closely relates to the Front Controller Pattern. In my opinion you lose nothing with pointing verything to a certain script, but win the flexibility do execute certain actions without having to repeat (and probably foget at some place) those actions.
So I would recommend to point all forms to one script.
Btw. it is the controller who handles the form processing in terms of web MVC.
Following on from my comment on Flavius' answer.....
The object encapsulating the form should be used for both presenting the form to the user and retrieving data sent back from the user. Using 2 different codesets to operate on the same dataset undermines the principle of encapsulation. Consider if your login form has a name and a password field. If you decide you want to process a sha1 hash of the password in place of the original value, you may have to modify 2 bits of code in 2 different places!
This does not mean that both instances of the form object need to be implemented within the same URL path; consider PHP's 'require' and auto_include constructs.
Where multiple input sets are multiplexed via the same URL path, this is referred to as a Front Controller pattern.
There are benefits and issues with Front Controller vs the more distributed approach.
Front Controller:
allows common processing to be implemented in one place only (e.g. authorization, logging)
moves structure of the application away from filesystem layout and into code, therefore control over application structure implemented within code
simplifies handling of bookmarks
Non Front Controller:
much easier to support
application structure evident from webserver logs
more robust - since breaking one script deos not break whole site
better performance - no need to load huge amounts of redundant code / deferred loading of processing target
Related
most of the modern PHP frameworks use data attaching method, for example:
View->render('login', $errors); // or
View::make('login')->with(array('errors'=>$errors);
I'm trying to establish a convention, where even if the View designers and the Controller developers do not have a direct communication, they can expect what data to put, and what data to receive,
I have thought of two methods, first using a class that takes care of rendering the views including the data, and this class would contain all types of data which will be used among the platform, second method is to have a naming convention to follow, I personally find the first method better, but I have to note that I'm not a skilled developer, I'm not sure what implications can that method have, which method would you choose?
perhaps another method?
For direct view rendering, you can use View::composer method.
View composers are callbacks or class methods that are called when a view is created. If you have data that you want bound to a given view each time that view is created throughout your application, a view composer can organize that code into a single location.
It is about auto rendering.
You communication convention with designers should be easily done through Separation of concerns pattern.
Blade templating syntax is ideal for that, since it separates logic out of your view. By logic, I mean all data that comes from you domain layer (model,db...).
Using {{$data}} syntax is pretty straightforward and easy to understand to designers.
When trying to adhere to established best practices like avoiding singletons, registry, static properties and base controllers, how I can populate my layout(and partials used by the layout) with data that is only used by the layout and common across all actions?
The typical scenario is menu which is built on variable data, like an database. Keeping separation of concerns in mind, the views/layout should never talk to an backend directly, but rather be told what to contain.
Using a front controller plugin is simply not possible without using the singleton "feature" in Zend_Layout. The plugin only knows the request and response object, neither has access to controllers, views or the layout.
Zend's action helpers have init/preDispatch/postDispatch methods. One can add action helpers to the HelperBroker (ex. using the bootstrap) and these will be executed in the normal application flow.
Using the init-method to inject data into the view is not possible since it's trigged before the controller/view is ready. preDispatch/postDispatch is possible, but not perfect, since these methods are always triggered when executing a controller action.
That means that all uses of the Zend_Controller_Action::_forward() will also execute the preDispatch/postDispatch in all action helpers. This doesn't have any big implications for the code except speed, I really do not want to be setting a view (or an view helper) variable several times. One can code around this issue using some sort of $firstRun variable, but I really don't want to track this in my own code.
Another method is doing this in the bootstrap, but in my opinion it really does not belong there.
So, how can I populate my layout/view helper with data from the database, doing it only once and still keep a good separation of concerns?
I've followed the ActionHelper approach, setting the view variables on the preDispatch method. It was the most logical place, in my opinion. In addition, my projects weren't using Zend_Controller_Action::_forward(), so I didn't have any speed concerns about multiple triggering of the helper.
Hope that helps,
You could go with Action Helpers as stated in this answer (take a look at the question too, its pretty much similar to yours)
I'd use action helpers too. Just fill the view variables and display them using plain PHP/partials/render/viewHelper (depending on complexity).
Your problem with multiple runs using preDispatch could be solved using
if (!($this->view->myVar)) { // or array_key_exist or isset - depending on your use case
$this->view->myVar = $someModel->getSomeData();
}
Which is just fine IMO.
I need help clarifying the correct structure and process flow for an MVC application in PHP.
I think I've got the concept round the wrong way because currently most of my processing is done (or at least initiated by) the Views. -- I kind of inherited this way of thinking from the company I'm working for, but now I'm not sure that they are understanding the MVC model correctly!
Having looked at it again I think that the proccess should be as follows (very basicly):
The users actions are sent to the Controller
The Controller process those actions using any Models required
The Controller then instantiates the relevent View and passes the required data to it
The View renders the page to the user
I'm also having some difficulty deciding wether the view should even have any real functionality in it or not.
i.e. Is it just a wrapper to hold the page data and load the required template files (header, page, footer etc.), OR should any functions to do with rendering data (i.e. preparing HTML and outputting HTML) be in the View?
Another question is does the controller 'hand over' to the model and have nothing to do with the actual DBconn (so that the Model acts like a Bouncer on the doors of the DB nightclub, and we're not on the list) OR does the controller 'own' the DBconn and simply lends it to a model when it needs it?
I'd really appreciate any help and advice anyone can offer.
Thanks
edit -- I found this helpful!
I'll answyer to your two last questions:
1) The Views should have basic output capabilities, for example escaping values to avoid security issues or display a html table starting from a list of objects. Another responsibility could be the translation of labels and other constant values (for example you could have $this->_('Your label') where function _($val) is a function included in all your view classes that translates the strings starting from a csv file).
2) Depending on the complexity application, you could have two sub-layers in the model layer. The upper layer is the classic model with the functionality of your entities. The lower level is the resource model class associated that performs the db operations. You could also have a single layer with your models that implements the DAO pattern. Anyway, the controller shouldn't have nothing to do with db connection.
Your bulleted assumptions are correct :). The main idea behind MVC is loose-coupling and interchangeability between components.
To answer your questions:
The view should be presentational only, so iterating through a list of models in the view and outputting them there is fine, but processing data in the view is not.
The model should not assume anything about the controller and the view. It should be easy for you to switch between a model that draws data from a database to one that draws data from another type of data source and this should not determine changes in the Controller. Fabrizio is right, you should check out the DAO pattern for an example on how to do this.
I really recommend taking a look at frameworks that implement MVC to see how they do it. Especially Spring - even if you're not a Java person, the implementation is very clean -, Rails, Symfony. For something more exotic take a look at Django.
I've been using the CodeIgniter framework for PHP and am enjoying it, but I notice that it seems to require a controller for every view. I'm wondering if there is a way to call a specific model from the view itself, rather than route through a controller. I understand that use of a controller is best practice in most cases, especially where the data from the model needs to be modified in some way, but I have cases where I just need to do a strict data pull to the view (which is loaded via ajax), and setting up a controller for that seems superfluous.
Any thoughts? Thanks in advance!
You're fundamentally misunderstanding MVC, at least as implemented in CI.
All URLs on your site (at least those that utilize the CI framework) are mapped to functions (methods) within controllers.
http://myCIsite.com/controller/method[/var1][/var2]...
It doesn't matter whether the URL is accessed via regular HTTP or via AJAX. This is always a one to one mapping. Because of this, you should think of the controller/method combination as the "web page". Do not think of the view as the web page.
Models and views are subordinate to controllers. The controller delegates specific responsibilities to them - database interaction for models, and page output to views.
Because models and views only serve to perform delegated responsibilities, their use is not required in any given controller/method. Help pages, for example, generally have no need to interact with a database, so there is no model utilized by the controller/method combination that serves a given help page. Likewise, form handlers frequently redirect to another page upon completion of processing. As such, there is no view corresponding to the form handler (but there is (likely) a view called from the controller/method in the redirected to page).
Furthermore, models and views do not necessarily correspond on a one to one basis with individual controllers/methods. Any given model can be loaded and used from within several controllers. Similarly, a controller could have a single monolithic view that is used by all methods, or each method could be assigned its own view. (Or, as I just said, a given controller/method could utilize no view at all.)
Finally, CI does not enforce strict MVC separation. You can interact with the database and echo HTML all from within the controller and CI will not complain. Nevertheless, this separation and delegation of responsibility is followed because logically separating the responsibilities makes the code easier to read and helps you follow the DRY principle in your coding.
The fundamental Understanding is that the "web page" corresponds to the controller/method. The view and model, when used, handle delegated responsibilities for the controller/method.
I'm wondering if there is a way to
call a specific model from the view
itself, rather than route through a
controller.
That's not possible as of what I know, the main abstract class of the CI controller imposes restriction to use a controller otherwise you will get a fatal error.
And actually what you say will break the best practice of MVC design pattern. You got to go to model through a controller not view.
I'm a bit confused as to exactly what you're trying to achieve. The controller's value, aside from just being a clean way to handle incoming requests, is to manage the interaction between the models and the views and to determine which views to load. It's also entirely reasonable to load model data directly from your views, but how did you get to your view in the first place?
I guess I'm just having a hard time seeing the context here..
To run a query via Ajax you still need to provide a URL / path in the javascript call. You can not get around the fact that a controller function has to "catch" this call; you can not map a url directly to a model. All you need is 3-4 lines of code in your controller.
Via URI routing you can map a URL to a different controller, so you don't "require a controller for every view". I always create a controller called "ajax" to handle those requests.
A basic ajax call with jquery can be something like this
$('#prod_img').load( "http://domain.com/ajax/get_img", {'color': 'blue', 'url_title': 'bla' } )
You can echo stuff in your controller, so rather than trying to bypass the controller you should be looking into how to do away with the views. This will actually be easy, you can load the db class in the controller just as you can in a model.
But if you really don't want to use MVC perhaps Codeigniter is not the framework for you.
You should read more into the principles of MVC.
Views are strictly for presentation of data, the model shouldn't communicate with views directly.
But still if that's what you want then just pass $this->db from the controller to the view and use it in the view.
Then again, this is NOT a good practice.
I recently read this post which led to a series of other posts that all seem to suggest the same idea: Models do everything, the View should be able to communicate directly with the model and vice versa all while the Controller stays out of the way. However, all of the examples shown are fairly simplistic and none really show an example of how anyone has tried to implement full handling of of a request / response cycle, which got me to wondering "should the model be responsible for handling the request (ie $_GET, $_POST, etc) itself?" and "should the controller only operate as a pass-through to instantiate the necessary model(s) and pass the model(s) to the view?". (In fact I found one example taken the extreme of embedding a Zend_Form object in the model)
From my reading of what Fowler says about MVC and just controller's in general it seems at first glance that the thinner the controller layer the better. But then I took the time to back through and study what he says about both MVC and Front Controller (which just muddies the waters because both patterns define controllers) and now my instincts suggest that Zend_Framework in implementing both of these patterns, has actually created a composite object that performs the functions of a Controller in MVC and those of a Command object in Front Controller (or some such).
So I'm wondering what the general opinions would be of others who have implemented similar patterns in their apps - do you handle the request entirely within the controller layer or do you make the model aware of the request and handle parameters directly within the model?
My first thought is to avoid handling any sort of request in the model. That is the job of the controller. Here is why: suppose you have a model that does handle your requests (GET or POST). That structure will likely work well initially. Now, suppose you want to add some sort of AJAX functionality or put up a service interface to your system. Now that you accept more than simple GET/POST, i.e. JSON or XML, your model will have to distinguish between each request type and know how to parse them. I believe that destroys a lot of simplicity and clarity of the model code. I agree that the controller layer should be thin, but it should also have a role and an expertise. For me a controllers expertise is to:
Handle incoming requests
Delivery data to the model
Request/accept data from the model
Pass the data's model to the view
I vacillate on how much the view should know about the model. Some people recommend the model go straight into the view, but I think that is fragile coupling. It frequently leads to logic in the view. Also, if you are working on a project where the team members working on the view are not as programming savvy as the main developers it puts a large burden on them to keep up with changes. I tend to package the data I hand to my views in a neutral structure instead of handing over the full models.
My interpretation of MVC is mostly pragmatic. The model's job is to model the domain you are working on and should not care where the data comes from. I frequently structure model code with the assumption that it could be used outside of the web application in perhaps a command line application or a desktop application. That sort of union rarely happens, but it leads to clear purpose of each layer. The controllers job is to move data between involved parties, be they client requests, the models, or the view. The controller should have very little domain logic, but that doesn't mean it doesn't have any code. Finally, the view should just look pretty. Hope that helps.
handling the user instructions/input (like HTTP requests) is the job of the controller. model is for working/manipulating/fetching the data and view is for showing the results to user. this means that connection between the view and the model is duty of a controller most of times.