MVC Fundamentals

I’ve read up a bit on the concept of MVC and have used it in the past, but feel as if I do not firmly understand where responsibilities lie.

Can someone tell me what I’m missing after reading my interpretation of MVC?

The Model represents the data, and performs all of the heavy lifting.

The Controller forms a bridge between user requests and Model functions.

The View contains layout and presentation representations, and should be as dumb as possible.

The View and the Model can both request actions of the Controller.

The primary role of the Controller in the context of Yii is to perform access control.

The View should attempt to minimize calls to the Model directly, instead going through the Controller.

Is there anything glaring about the following example?

I have a view that presents a list of models in tabular form. Each row of the table has a drop-down box. The drop-down box allows the user to change the state of a model or generate a PDF representation of the model directly in the browser.

The way I have it set up, the name of each drop-down box contains the id of its database record (i.e. dropdownbox1 for id=1). Thus, I can tell which record should be subject to the action submitted. The problem is that the action to be requested of the controller is dependent on the value of the drop-down box.

Here’s the way I’ve set it up:

In the first few lines of the view, I

-Check to see if $_POST contains anything

-Call Yii::app()->controller->run(‘processPost’)

-The controller calls Model::processPost()

-The model changes its state if the value of the drop down box is between 1 and 3

-Otherwise, the model calls redirect(‘controller/generatepdf’)

Thanks for reading my wordy post. :D




Here's the way I've set it up:

In the first few lines of the view, I

-Check to see if $_POST contains anything

-Call Yii::app()->controller->run('processPost')

-The controller calls Model::processPost()

-The model changes its state if the value of the drop down box is between 1 and 3

-Otherwise, the model calls redirect('controller/generatepdf')

I would check the contents of $_POST in the controller, not the view.

controller->run() is for running actions, not regular methods.

The model should not redirect the user, the controller should.

The primary use of the controller is not access control, although that is one thing it does. It handles the request.

For the drop down lists, I would recommend using this to print it: http://www.yiiframework.com/doc/api/CHtml#activeDropDownList-detail

And see: http://www.yiiframework.com/doc/guide/form.table

My version of it would be:

  • request starts in controller

  • load models that are being displayed

  • if post data set (

    • loop through models and set their attributes with CModel::setAttributes()
    • $model->save()
    • in model beforeSave event, check if action is selected and if so act accordingly
  • )

  • print view

Something like that… there is no one way to do it. i think you had too much logic in the view though

Your interpretation of the MVC is not quite correct. Here’s a short description which might help you better understand the principles.

  1. View: is a representation of information/data and can be used to collect user input.

  2. Model: contains the business logic, i.e. perform calculations, set states, store data, etc.

  3. Controller: runs the business logic defined in the model(s) and/or renders a view.

If the model requires user input, the controller should render the appropriate view.

Next the controller collects the user input from the view and passes it to the model.

If the model should require to redirect the user (to some business logic or a particular view), let it return some specific value which tells the controller to redirect the user to the controller action which then executes this particular business logic or view.

Thanks for the suggestion. Why didn’t I think of checking and processing $_POST inside the controller? I like that. I still don’t think CHtml::activeDropDownList would be the most appropriate solution, just because the drop down serves several purposes in my interface, namely it can:

-Set the state of the model

-Re-direct to an action that generates PDFs

-Re-direct to a detailed view of that record

Thus, not every item in the drop-down will change a model attribute.

Thanks for this explanation! I’ve read some general texts on MVC, and done some coding using Qt4’s MVC, but it’s hard to understand where the rubber meets the road unless it’s put into context. I’ll get it through my thick skull eventually.

From your explanation, I can imagine the following scenario:

  1. User provides input to a form and hits submit

  2. The target for ‘submit’ is ‘’ (goes to the same action)

  3. Check $_POST in that action of the CController derived class

  4. Controller makes changes / calls functions in the model

  5. If the model reports an invalid state (i.e. state set to "PAID" with balance != 0), controller should spit out a warning message for a javascript alert when rendering page.

As an aside, I have a form that gets submitted when the user hits return on a text field. I was having problems with the ‘onsubmit’ event not firing (apparently this is a problem when ‘submit’ is called programmatically instead of via a submit button). Here’s my fix for it.




===================================================================

--- framework/web/js/source/jquery.yii.js       (revision 46)

+++ framework/web/js/source/jquery.yii.js       (working copy)

@@ -34,6 +34,7 @@

                        inputs.push(input);

                });


+               jQuery(f).trigger('onsubmit');

                jQuery(f).trigger('submit');


                jQuery.each(inputs, function() {