Where does Zend_Form fit in the Model View Controller paradigma - model-view-controller

The Zend Framework is mainly meant for MVC use. One of the very usefull components is Zend_Form.
I have a bit trouble finding the place of Zend_Form. Is it part of the view, model, or controller and which responsibilities should I give it.
The thing is, Zend_Form does two things: decorate and render the form and validate it. The first is a real view task, the second a real model task.
Now the most common use seems to be to have the forms interact with the controller only, effectively putting both tasks (rendering and validating) to the view/controller.
Another option given by Matthew Weier O'Phinney is to attach the form to your model, and adding the later view options in the controller.
So, I'm doubting. Where in the MVC pattern should I place Zend_Form and how should I use it?
Edit Good answers so far, thanks! I will be awarding the bounty an hour or two before it expires, so please give an answer if you have some more thoughts!

Zend_Form can be viewed at different points. It can't be considered at all as part of just one layer of MVC pattern.
First of all Zend_Form use decorators and view helpers to render the form, at this point it is part of view layer.
Then, Zend_Form does part of the model job filtering and validating the content.
We know that Controller layer render input from the view and pass it to the model. Actually, the controller layer decide which resource to load from model layer and then perform the corrects calls.
When you call Zend_Form from controller layer, you can consider that you are calling one model resource to perform valitations and filtering actions and decide whether or not this is a valid input. For example:
public function newAction()
{
$form = $this->getForm();
if($this->getRequest()->isPost())
{
$formData = $this->_request->getPost();
if($form->isValid($formData))
{
$Model = $this->getModel();
$id = $Model->insert($form->getValues());
}
}
$this->view->form = $form;
}
Tie Forms to the model can be considered a good pratice because when you are performing filtering and validation actions you are on model layer. So, as Matthew proposed:
class Model_DbTable_Users extends Zend_Db_Table
{
protected $_name = 'users';
protected $_form;
public function getForm()
{
if(!$this->_form)
$this->_form = new Form_User();
return $this->_form;
}
public function add($data)
{
$form = $this->getForm();
if(!$form->isValid($data)) return false;
if($form->getValue('id'))
{
$id = (int) $form->getValue('id');
$this->update($form->getValues(), 'id =' . $id);
}
else
{
$id = $this->insert($form->getValues());
}
return $id;
}
}
From the standard directory structure we can see that Forms aren't in the model folder nor in the view folder because Zend_Form is a specific class that tie many resources and layers together. If you check the Matthews post you will realize that this is exactly what is being said when the action url is set on the view script and the form is tied to the model.
Finally, you can analyze your context and pick up one of these two approachs.
Currently, my choice is to tie forms to models. Looks nice! And make a lot of sense to me.

IMO, Zend_Form is designed to wear multiple hats. It is, in fact, a bridge between the view and model with a giant support beam from the controller.
Instead of assigning a Form to a Model, consider assigning Model(s) to a form.
In the Model layer, you can have a a getFormInputs method that could return the Elements needed to input data. The model doesn't care what form is going to use it, it just makes it available to any from that wants them.
Now in your form layer, make a setupInputs method that will loop thru an array of models to grab all the inputs. If there was only one model, add the inputs to the form. If there was more then one model, make sub forms.
Your controller will initiate the form and pass the values back to model (see Keyne's newAction method)

Zend_Form does often feel like the odd man out. I think everyone's mileage varies.
Lately, most of my administrative interfaces have been very drag + drop AJAX-y, and they require a good deal of html and javascript - actual form elements are sparse. So I chose to eschew a lot of the features of Zend_Form and use it as a fancy view helper with filtering. All my validation is done on a separate layer in the model.
I think O'Phinney's idea makes a lot of sense as well. Here, he's choosing to think of the form almost as a component of the domain object - where he can add business logic. This sounds just fine, as long as you're careful to keep all the view logic for the form separated. As he notes, it's about making semantic sense. There isn't necessarily a hard and fast rule.

Related

Input validation in MVC

I need a little help regarding design of MVC .
Most of the tutorials of MVC and CODEIGNITER are doing input validation in controller. Is it a good practice ?Suppose we implement REST or SOAP API then we are going to have different controllers, and for all those controllers I need to replicate my code. Later if any of the validation rule is changed, it will get rippled into all controllers. Shouldn't all the validation should be inside Model instead of Controller ?
One more thing I would like to ask. As I am trying to keep my functions as cohesive as possible, I am getting one to one relation between functions of model and controller. Is it ok or I am doing things wrong ?
Regarding doing input validation in Controller
Ans. Yes, that is the generally accepted practice in most MVCs. However, during the past few years, due to the advent of AJAX frameworks and more adoption of JavaScript, many UI validations get done in UI itself(called client-side validations). These are generally displayed as javascript alert boxes and do not allow user to go ahead unless he fixes these errors. So, I would say Controllers/View helpers are de-facto places where validations are done but you should consider client-side validations wherever feasible. It also saves you trips to the server.
If you expose the same as functionality as SOAP/REST
Ans. Now-a-days you can annotate the same controller methods to make them work as web service endpoints. So, your controllers can service both web-based requests and also SOAP/REST requests.
But one note of caution - your form-beans/backing beans should be very well designed. I have seen code where hibernate model objects are used as form-backing objects. This makes it tricky when you generate a WSDL out of the form-backing objects as hibernate model objects may have many linked entities and one ends up with very complex xml structures in the request/response.
But still, if you design your backing-beans as fine-grained, i.e. not having complex objects, then you should be comfortably placed in using your existing controller/controller methods as web service endpoints for both SOAP/REST.
Regarding the validations being inside Model layer
Ans. You can use this thumb rule to determine where to place which validations -
Business validations should happen in models/services
complex client validations, which are not feasible in client-side, should happen in controllers/view helpers
UI validations (formatting/empty checks) should happen via client-side/javascript validations
Regarding one to one relation between functions of controller and model/service
Ans. Its fine. Just remember to have one controller method talk to its respective model method. And if multiple models are needed to service a request, then that model method should act as an aggregator of information from multiple models i.e. the controller should contact its main model and the main model should contact other models.
Is it a good practice? In my experience yes.
One thing to keep in mind is that any given controller can display an number of different pages. For example, consider a "Dashboard" which could have multiple tasks each of which requires its own page.
A rough pseudo-codeish "Dashboard" controller might look like this:
class Dashboard extends CI_Controller {
public function __construct(){
parent :: __construct();
$this->load->helper(array('form', 'url'));
$this->load->library('form_validation');
$this->load->model('somemodel_model');
}
public function index(){
//displays a task selection page with links to various tasks
}
public function admins(){
//some kind of interface to display and edit admin level users
}
public function users(){
//CRUD for dashboard users
}
}
With this controller the task selection page is opened with baseurl/dashboard, adminstrator's page with baseurl/dashboard/admins and user CRUD with baseurl/dashboard/users. Because each of these share the same Class, code needed by all/many of these pages (like validation) can be implemented in the constructor and/or with private methods. You probably already know all this. Keep in mind that AJAX responders can also reside in a controller using the same technique.
In regards to keeping the validation rules DRY and easing the work required for changes to rules CI can store sets of rules in a config file for easy reuse in multiple situations. Read about it.

Where to operate on data?

My controller calls a repository which gets data from a model, this is then returned up the chain to the controller, which outputs the data in a view.
Where should I operate on this data? For example, perhaps I wish to add a random object to the data:
//Controller
$data = $this->repository->getAllRows();
Where should this go? in the controller? in the eloquent repository?
$data->splice(0, 5, [$myNewObject]);
Depends on what you are doing it for. If its directly related to data, you can place it in model, or its directly related to logic, keep it on controller.
Like you can keep it on model if you need like:
//on model
function getRecentRows()
{
$data = .....
return $data->splice(0, 5, [$myNewObject]);
}
You will keep this on controller if
//on controller
$data = $this->repository->getAllRows();
$data->splice(0, 5, [$myNewObject]);
$datas->each(function($item){
$item->is_featured = true;
});
//return view with data
This might not be the exact answer. You have to provide exact case here.
It depends, but generally I like to keep my models clean without any logic.
Now if that is a single action, just do it in the controller.
If it's a common task and you want to share it along other controllers, you have two options:
Creating a class so you can use that functionality sometimes inside
your controllers
Creating a controller with your operating data functions and extending all of your controllers from it.
I usually adopt this last one, specially when creating API's where I want to create filters to hide some data.
EDIT
This is a screenshot with a structure that I used for my last project named Paka:

Access controller method from inside a model

How do I access a controller method from inside a model?
You don't.
Although it is technically possible, if you think that you need to, it suggests a flaw in your application's design.
The Controller layer is the backbone of you application and meant to handle requests from the user, talk to the Model layer, and stitch together the output in the View. Your Model layer should be blind to the Controller and View, but deal with data manipulation only. This is an over-simplified explanation of the MVC pattern (you can find resources for that elsewhere).
Your Codeigniter models should be reusable from any controller, and not dependent on them. There are many solutions to solve whatever problem it is that you have: You can pass data into a model in a number of ways, or you can use the result of a call to a model's method to perform an action in your Controller.
You can use like this:
class some_model extends Model
{
function getController()
{
$controllerInstance = & get_instance();
$controllerData = $controllerInstance->getData();
}
}

MVC: pass model / model data to a view from a controller?

If a view needs to acces data from a model, do you think the controller should:
a) pass the model to the view
b) pass the data of the model to the view
c) neither; it shouldn't be the controllers concern. Let the view access the model directly to retrieve the data. Only let the controller give some parameters the view needs to filter the data from the model.
d) it depends on the situation.
e) none of the above, but [...]
Thanks
After some debate in the comments to an answer that was deleted by the user, maybe this needs clarification. My view of the MVC architecture is biased towards that of the Zend Framework (php) in which an action in a controller by default has a default view assigned to it. So it's not so much the model that dictates which view is approporiate, but rather the controller. Do you feel the model should dictate what view is appropriate? The only way I see fit to let the view be build based on a model, is by letting the controller pass the model to the view. Are there other techniques to let a view access a model without the controller being involved? Or is it perfectly fine to let a controller pass the model to a view, so that the view can be build based on the models attributes?
e) None of the above; pass in a view-optimised "ViewModel".
Example in ASP.NET MVC:-
public ActionResult Details(int id)
{
Product p = ProductService.GetProductById(id);
if(p == null) { return RedirectToAction("Index"); }
ProductViewModel model = new ProductViewModel(p);
return View(model);
}
both a) and b) "will do" subject to d). Never ever c).
Typically, the ViewModel just encapsulates the Model (if nothing complicated is going on, your view could access the model directly via ProductViewModel.Product). If the view needs to do anything complicated with the Model however, it's the ViewModel's responsibility to do that, rather than the responsibility of the Controller, or the View.
This keeps your concerns nice and segregated. Your Controller doesn't care exactly what specific data your View needs (beyond the fact that it's rendering some Details of a Product), or especially what format your View needs that data in. Your View doesn't depend on the implementation details of your Model. Your Model doesn't have to concern itself with how it's being Viewed. If you have two Views rendering Products (e.g. Create, Edit, Summary, MoreDetails etc), those Views can have different ViewModels to expose only the data that each specific View needs, so your Views aren't depending on eachother. Lovely :)
Some further reading from various viewpoints:-
http://www.thoughtclusters.com/2007/12/datamodel-and-viewmodel/
http://stephenwalther.com/blog/archive/2009/04/13/asp.net-mvc-tip-50-ndash-create-view-models.aspx
http://www.nikhilk.net/Silverlight-ViewModel-MVC.aspx
I think ViewModels are a particularly .NET thing, but I see no reason at all why the pattern can't be used in PHP.
Hope this helps.
Ideally, it should "pass the data of the model to the view" so the view doesn't need to know any explicit structure of the model and thus be more reusable and designer-friendly.
But practically, "pass the model to the view" works as just fine. Most of the time you will need a new view anyway because clients never share favorite colors (if you know what I mean :-) so views re-usability doesn't justify having a lot of tedious code required to copy data from the model to the view.
What you should concern more about is the modularity of the controller itself, since many websites do share common functionalities (controllers) such as web forums or a news listing but not looks (views)
This is late I know, but I'm having this issue on a project I am working on. I started with a) - for simplicity - and now running into road blocks.
I am coming around to this method:
e) None of the above; pass in a view-optimised "ViewModel".
because it avoid bloating both your model classes (instances of which are "transaction objects") and your views. For example, you may need to render a number with a specific number of decimal places (this is the problem I am having now).
With an intermediate "ViewModel" this is easy - you just write the relevant ViewModel "getXXX" method to return the number formatted how you wish.
If you just pass the model directly into the view, you will need to specify it in the view every time you use this figure (going against DRY - don't repeat yourself), or alternately, add a rendering method to your model classes (which goes against a class being for one purpose only).
Cheers
a) pass the model to the view
Otherwise the controller is manipulating the view via screening the model. This is what would happen in "b) pass the data of the model to the view". The b) option doesn't really even make sense in the pure MVC pattern. After all, the model IS the data. If the model is changed for consumption, a view has been applied, whether you choose to do it in the controller and pass it off as a controller function. What happens when you have a different view? Does the controller screen its data differently? You soon have two views for model, the controller sub-view and the view itself.
For me that's e).
As already mentioned here, ideally the view and the model are decoupled. The way I prefer to implement this is to have a viewHelper for a model. This has the API the view can use to get the data. Now views are not affected by changes in the model and the view doesn't need to 'get' the internals of the model. These are hidden away by the viewHelper.
example:
class Post {
public function export(ViewHelper $helper) {} // I try to avoid getters when I can
}
class PostViewHelper {
public function getTitle($parameters) {} // title of current post in the loop
}
class PostView {
private $helpers = array();
public function loadTemplate($path) {}
public function addHelper(ViewHelper $helper, $name) {}
public function __get($key) {} // if exists $this->helper[$key] etc
}
in a template
<h1><?php $this->post->getTitle(); ?></h1>
You may want to implement this differently. But my point is in how the view and the model are decoupled, introducing an intermediate viewHelper wich creates the view/template API.
I don't think it's that complicated. a or b.
The controller's job is to manage the relationship. It finds the model and view and provides the view all the model data it needs to do its job. That's it. MVC doesn't dictate the exact form the data takes.
(a) Start simple. It's pretty natural to pass the model objects directly to the view. If you have a page about a Foo, just pass the Foo.
(b) But at times-- and only at times-- you create a value object / DTO to get the data to the view (called a ViewModel above). Do this when there's a mismatch between the view and the native model, such as summary views. If the view is presenting a summary of 1,000,000 objects, you don't want to hand the view the model objects; you want to hand the view a summary of the 1,000,000 objects.
And the exact implementation really depends on the language and framework you are using. But I think these guidelines are a good start.
uhh b.
i dont really see the difference between a and b other then some technicallity of how you will be passing data.
usually you pass a map of data to the view with some data from the model

CodeIgniter Model / Controller and UserID

My Models in CodeIgniter need to check that a user is authorised to perform the given action. Inside the Models I have been referencing using $this->session->userdata['user_id'].
My question is - should I be setting a variable to $this->session->userdata['user_id'] in the Controller and passing this to the Model, or simply checking it inside the Model ?
Does it even matter ? I suppose passing $user_id into the function would make it (slightly) more readable. What are the arguements and recommendations for / against ?
You can choose between data that is fundamental to your application and data that is incidental to a given model member function. Things that you use everywhere should be guaranteed (base members, globals, etc.), and things used only in the current function should be parameters. You'll find that using implied variables (like $this->session->userdata) in many places in your models and views will become spaghetti quickly, and will be unpredictable if you don't bootstrap them properly.
In my CodeIgniter projects, I add a custom base model and controller that inherit from the CI framework, adding their own member data that is used everywhere in the app. I use these base classes to provide data and functions that all of my models and controllers use (including things like userID). In the constructor of my_base_controller, I call the CI base constructor, and set up data that all of my controllers and views need. This guarantees predictable defaults for class data.
Strictly speaking $this->session->userdata['user_id'] belongs to the controller.
Models deal with data only... controllers, by definition control the flow of the data...
and authentication is a form of data control... (IMHO)
Codewise, I follow this procedure
class MyControllerName extends Controller{
function MyMyControllerName(){
parent::Controller();
$this->_user_id=$this->session->userdata['user_id']; //<-- define userid as a property of class
}
}
And then, say one of my functions foo() requires authentication.. I would do this
function foo(){
$this->_checkAuthentication(); //should short out if not authenticated
//rest of the function logic goes here
}
the _checkAuthentication() can be simplistic like:
function _checkAuthentication(){
if(!isset($this->_user_id) && $this->_user_id<=0){ /or any other checks
header("Location: ".base_url()."location_of/user_not_authorised_page");
exit;
}
}

Resources