Question about MVC concept and Yii

Hi all:

As I understand the MVC concept of programming,

  • the (barebone) view should only handle the presentation,

  • the (thin) controller is the intermediary between the view and,

  • the (fat) model, where the business logic should reside.

I realize that a strict implementation of the above is not always practical nor feasible so the rules can be broken. However, I’ve noticed that in many of the code samples posted here it’s pretty common practice to have the view interact directly with the model, especially when using a database. As a MVC/PHP/Yii newbie myself I know I’ve done it a lot. For example, to load a dropDownList from the database I see code in the view similar to the following:




<div class="row">

	<?php echo $form->labelEx($model,'mymodel_country_code'); ?>

	<?php

		$modelCountries = Countries::model()->findAll();

		$listCountries = CHtml::listData($modelCountries, 'country_code', 'country_name');

		echo CHtml::activeDropDownList($mymodel, 'mymodel_country_code', $listCountries, array('empty' => '(Select country)'));

	?>

	<?php echo $form->error($mymodel,'mymodel_country_code'); ?>

</div>



The above tells me that the view:

[list=1]

[*]is querying the model directly,

[*]formatting the retrieved data,

[*]rendering the dropDownList (which is also active therefore directly updating the model), and

[*] doing error processing.

[/list]

I think that even combining the statements into one long php expression makes no difference. Are these conclusions correct?

To me this approach is not scalable and will incur in additional bandwidth costs from the hosting provider as the website usage grows, plus it’s not ‘elegant’. I would prefer to have the view just accept input data and render the page, the controller handling the message traffic (with perhaps a minimal amount of processing of its own) and finally the model doing the heavy work of processing business logic and database interaction.

My question is, do y’all have any suggestions on how to improve on this scenario (using Ajax perhaps)? Specific scenarios and code samples would be greatly appreciated. Thanks.

In the example you posted, you can pass $listCountries from the controller to te view.

And in the controller you can obtain $listCountries calling a custom method in your model.

MODEL




public function getListCountries(){

   $modelCountries = Countries::model()->findAll();

   $listCountries = CHtml::listData($modelCountries, 'country_code', 'country_name');

   return $listCountries;

}



CONTROLLER




   //At some point of some action

   $this->render('theView',array('mymodel'=>$someModel,'listCountries'=>$model->listCountries));



VIEW




 echo CHtml::activeDropDownList($mymodel, 'mymodel_country_code', $listCountries, array('empty' => '(Select country)'));



But I prefer a simplest way:

MODEL




public function getListCountries(){

   $modelCountries = Countries::model()->findAll();

   $listCountries = CHtml::listData($modelCountries, 'country_code', 'country_name');

   return $listCountries;

}



CONTROLLER




  //At some point of some action

   $this->render('theView',array('mymodel'=>$someModel)); //Yo not pass the $listCountries variable.



VIEW




echo CHtml::activeDropDownList($mymodel, 'mymodel_country_code', $mymodel->listCountries, array('empty' => '(Select country)'));

   //Instead use directly the method from the model that you already pass to the view



PoL, thank you for your prompt reply. I had already found a technique similar to what you propose, so the purpose of my post was to find out if I’m on the right track:

Model:




/**

 * Returns a list of countries ordered by country code

 * Accepts $_POST or command line

 */

public function findAllCountries()

{

	$criteria = new CDbCriteria(array(

		'select'=>'country_code, country_name',

		'order'=>'country_code ASC',

		));

	$ctrylist=CHtml::listData($this->findAll($criteria), 'country_code', 'country_name');

	if (isset($_POST['country_list']))

	{

		foreach($ctrylist as $value=>$name)

		{

			echo CHtml::tag('option', array('value'=>$value),CHtml::encode($name),true);

		}

	}

	else

	{

		return $ctrylist;

	}

}



Controller:




/**

 * Returns a list of countries

 */

public function actionFindAllCountries()

{

	if(isset($_POST['country_list']))

	{

		return Countries::model()->findAllCountries($_POST['country_list']);

	}

}



But unfortunately got stuck in the view part – even tried eager loading using CHtml::ajax() to no avail – and especially when updating an existing record, where the view would not present the attribute’s data. I will try your suggestions. Any more? Gracias…

You sould not do echoes in your model.

Cause, the model can be used by other thing than a WebApplication.

As you say:

  • the (barebone) view should only handle the presentation,
  • the (thin) controller is the intermediary between the view and,
  • the (fat) model, where the business logic should reside.

My bad, I just realized I was breaking my own intentions :(

I’m still not clear on the controller part:




$this->render('theView',array('mymodel'=>$someModel));



The data part of the function says to pass ‘mymodel’ (instead of the customary ‘model’) and $someModel (instead of the default $model); are these substitutes for the Countries model (that is a parent of ‘mymodel’)? Should I not pass these in addition to the default ‘model’/$model?




$this->render('theView',array(

   'model'=>$model,

   'mymodel'=>$someModel

));



Please explain. Thanks again.

Never mind, I got it working. Now for the next issue: how to handle (database) dependent dropDownLists using this mantra…

Hello.

My post is not answer to your question, but it’s related to the name of this thread. MVC concept.

I created thread with similar topic. In this thread is published a Yii PDF manual for absolute beginners. Manual is continuously updated and it’s NOT finished yet. It contains basic (and will contain more and more) facts and how-tos.

http://www.yiiframework.com/forum/index.php?/topic/6129-total-fresher-in-php-frameworks-and-yii-i-dont-understand-tutorials/

Thank you for your message. I had already read your tutorial and found it very helpful, particularly section 5.6.1 on Ajax.