Question regarding the right implementation

Hello!

I am currently developing a small application with Yii which is supposed to manage people and companies with relations and so on.

My problem now is, that I would like to use CTabView to seperately view people in different categories in coresponding tabs using only the (slightliy modified) list action. Therefore I extended CTabView to receive a "criteria" per tab which is later passed on to a CDbCriteria to ->findAll($criteria) the desired records and display different data with the same list-view in each tab. This part is already working so far, but now I need to be able to export the data viewed in the current tab to a CSV file. I wrote a class that is able to export any model I throw at it.

My only problem is how to "tell" the export method what we are viewing currently, because until now I am only able to export either all records or no records at all.

It sounds a bit confusing even to me as I read my own posting … so if you need further explanation please feel free to ask.

Thanks in advance!

ah, what the heck. I figure the code says more than a thousand words…

in the controller I render the index

public function actionIndex() {





		$this->render('index');





	}

index.php looks like this:

$tabs = array(


	'tab1' => array(


		'title' => 'Alle Personen',


		'list' => '/person/list',


		'data' => array(


			'model'=>'Person',


			'condition'=>'deleted=0',


			'order'=>'last_name',


		),


	),


	'tab2' => array(


		'title' => 'Ordentliche Mitglieder',


		'list' => '/person/list',


		'data' => array(


			'model'=>'Person',


			'condition'=>'deleted=0 AND type_membership="O"',


			'order'=>'last_name',


		),


	),


	'tab3' => array(


		'title' => 'Firmenmitglieder',


		'list' => '/person/list',


		'data' => array(


			'model'=>'Person',


			'condition'=>'deleted=0 AND type_membership="F"',


			'order'=>'last_name',


		),


	),


	'tab4' => array(


		'title' => 'Studenten',


		'list' => '/person/list',


		'data' => array(


			'model'=>'Person',


			'condition'=>'deleted=0 AND type_membership="S"',


			'order'=>'last_name',


		),


	),


);





$this->widget('CustomTabView', array(


	'tabs' => $tabs,


	'viewData' => $data,


));

The modified TabView has this renderBody

protected function renderBody() {


		foreach($this->tabs as $id=>$tab)


		{


			$inactive=$id!==$this->activeTab?' style="display:none"' : '';


			echo "<div class="view" id="{$id}"{$inactive}>n";


			if(isset($tab['content']))


				echo $tab['content'];


			else if(isset($tab['view'])) {


				$this->viewData['tab'] = $id;


				$this->getController()->renderPartial($tab['view'],$this->viewData);


			} else if (isset($tab['list'])) {





				$criteria=new CDbCriteria;





				$criteria->order = $tab['data']['order'];


				$criteria->condition = $tab['data']['condition'];





				$pages=new CPagination(Person::model()->count($criteria));


				$pages->pageSize = 20;


				$pages->applyLimit($criteria);





				$personList=Person::model()->with('email')->findAll($criteria);





				$this->viewData['pages'] = $pages;


				$this->viewData['personList'] = $personList;


				$this->getController()->renderPartial('list', $this->viewData);


			}





			echo "</div><!-- {$id} -->n";


		}


	}

which brings us back to the controller, actually the list action

public function actionList($options=null)


	{


		$criteria=new CDbCriteria;


		$criteria->order = 'last_name';





		$criteria->condition = 'deleted=0';





		$pages=new CPagination(Person::model()->count());


		$pages->pageSize=self::PAGE_SIZE;


		$pages->applyLimit($criteria);





		$personList=Person::model()->with('email')->findAll($criteria);





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


			'personList'=>$personList,


			'emails'=>$personList->email,


			'kategorie'=>$personList->kategorie,


			'pages'=>$pages,


		));


	}

Now I want some kind of link or button, that can tell my export action what to do.

public function actionExport() {


		$criteria = new CDbCriteria;


		


		$sort = new CSort('Person');


		$sort->applyOrder($criteria);





		$people = Person::model()->findAll($criteria);





		$export = new Export($people);


		$export->outputCSV();


	}

please help…  ???

Create a function that gives you the data you want to display.

Use that function to get the data to display AND get the data for exporting.

Store the parameters to that function in a session variable or a hidden input in your form - and use them again when you need to export.

That sounds good… I'll give it a try when I get home later.

Where would you put that method - in the model or in the controller?

The model is supposed to be a interface to your data.  So if it's quite general function for getting specific data - it probably should go in the model.  That way you can use it from any controller.

If it's specific to just that controller and you think it will never be required outside it, it's probably easiest to keep it in the controller.

Also - be careful of using session variable (go for hidden input field instead).

If someone opens multiple instances of your page then clicks on 'export' on the first page he opened - he would get data according to the last view he was in (on a different page).

Thank you! That did exactly what I had in mind.

Here is what the method looks like (btw. I put it in the Controller)

public function getPeopleList($criteria=null) {


	 	


		// define the conditions that have to be met by all records


		$condition = array(


			'order' 	=> 'last_name',


			'condition' 	=> 'deleted=0',


		);


		$initCrit = new CDbCriteria($condition);


		


		// list of fields we wanna check


		$fields = array(


			'type_membership',


			'category',


			);


		


		foreach($fields as $field) {


			if(isset($_GET[$field]) && $_GET[$field] != "") {


				$criteria[$field] = $_GET[$field];


			}


		}


		


		if($criteria != null) {


			foreach ($criteria as $field=>$value) {


				$tempCrit = new CDbCriteria( array(


					'condition' => $field.'="'.$value.'"',


					));


				$initCrit->mergeWith($tempCrit);


			} 


		}


		


		$pagination = new CPagination(Person::model()->count($initCrit));


		$pagination->pageSize = self::PAGE_SIZE;


		$pagination->applyLimit($initCrit);


		


		// TODO: join with company and categories


		return array(


			'personList' 	=> Person::model()->with('email','kategorie')->findAll($initCrit),


			'pages'		=> $pagination,


			);


			


	 }