Access controller method from model

Hi all,

A beginner’s question from someone new to OOP. In my app, users can sign up with just an email and a password. However, some content is only visible to those who provided us with more info. Hence, I need to test in the database whether all user fields are filled out. To do so, I created a method in the model, which is called from the controller. This method in the model needs to access a function from the controller and I don’t know how to access it.

$model->loadModel(); doesn’t work. $this->loadModel(); obviously doesn’t work because $this refers to the instance of the model.

Any help would be much appreciated. Cheers…

Method in model User:


	


        // tests whether all required fields of a table $testAllDataProvidedTable are set

        // used by actionIndex of UserController

        public function testAllDataProvided($testAllDataProvidedTable)

        {

            // needs to be loaded so $model->[required field] can be loaded in array $requiredColumns

            $model = $this->loadModel(Yii::app()->user->id);


            // set intial value of variable, will be set to 0 if one field is empty

            $allDataProvided = 1;


            // set required fields for tables

            if ($testAllDataProvidedTable == "tbl_user") {

                $requiredColumns = array(

                    $model->tbl_user_salutation_id,

                    $model->first_name,

                    $model->last_name,

                    $model->address_1,

                    $model->address_2,

                    $model->postcode,

                    $model->city,

                    $model->tbl_state_id,

                    $model->phone,

                    $model->email,

                    $model->tbl_user_interest_id

                );

            }




            // iterate through each field and if one is empty, set $allDataProvided to 0

            foreach ($requiredColumns as $value) {

                if (empty($value)) {

                    $allDataProvided = 0;

                }

            }


            // break the reference with the last element, http://php.net/manual/en/control-structures.foreach.php

            unset($value);




            // return value of fucntion

            if ($allDataProvided == 1) {

                return true;

            } else {

                return false;

            }

        }


	

}

UserController:




	/** This is where user gets redirected after login

	 * Welcome screen after logging in

	 * @param integer $id the ID of the model to be displayed

	 */

	public function actionIndex()

	{

		// load all attributes and methods from db / model User

		// by using the ID set in UserIdentity.php

		// to see how to overwrite Yii::app()->user->id with id instead of email, see Agile-Web-Application-Development-with-Yii11-and-PHP5-eBook09022011_1063898.pdf p. 165

                $model = $this->loadModel(Yii::app()->user->id);

		

                // for testing whether all required fields in tbl_user have been filled out as a requirement for selling / buying

                // $model->$allUserDataProvided is declared in model User and set by actionBuy() and actionSell() in UserController

                // by calling method testAllDataProvided in UserController

                $model->allUserDataProvided = $model->testAllDataProvided("tbl_user");




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

			'model'=>$model,

		));


		 

	}


	/**

	 * Returns the data model based on the primary key given in the GET variable.

	 * If the data model is not found, an HTTP exception will be raised.

	 * @param integer the ID of the model to be loaded

	 */

	public function loadModel($id)

	{

		$model=User::model()->findByPk((int)$id);

		if($model===null)

			throw new CHttpException(404,'The requested page does not exist.');

		return $model;

	}




hi, to get the controller you can use


$controller=Yii::app()->getController();

although i would rather use the loadModel code in the User model, that way the model is not dependent on the controller and not tightly coupled

A model shouldn’t depend on any controller. A controller loads a model, then calls it’s “testAllDataProvided” method and makes a desicion whether to allow a user to see some content or not.

u should change the approach a bit. u already fetched the $model in the actionIndex() why fetching it again in the testAllDataProvided(). Pass the $model itself to the testAllDataProvided().

Try like this:


//UserController:

        public function actionIndex()

        {

                $model = $this->loadModel(Yii::app()->user->id);

                $model->allUserDataProvided = $model->testAllDataProvided($model);


                $this->render('index',array('model'=>$model,));

        }


//Method in model User:

        public function testAllDataProvided($model)

        {

            $allDataProvided = 1;


            // set required fields for tables

            if ($model->tableName() == "tbl_user") {  // check the table name u want to use

                $requiredColumns = array(

                    $model->tbl_user_salutation_id,

                    $model->first_name,

                    $model->last_name,

                    $model->address_1,

                    $model->address_2,

                    $model->postcode,

                    $model->city,

                    $model->tbl_state_id,

                    $model->phone,

                    $model->email,

                    $model->tbl_user_interest_id

                );

            }


            foreach ($requiredColumns as $value) {

                if (empty($value))

                    $allDataProvided = 0;

            }


            unset($value);


            // return value of fucntion

            return ($allDataProvided == 1);

			

        }

}



check out how it goes…

Also u don’t need to check the tableName of the $model with in the instance of model.

Its like u have created object of User class & withIn that object checking whether its the object of the User class!!!

u need to check if u r calling this function from outside the model instance or is generated dynamically.

If u r going to use if for more than 1 model better make it a global/static function:


public function testAllDataProvided($model){

	switch ($model->tableName()) {

		case 'tbl_user':

			$requiredColumns = array(

				$model->first_name,

				$model->last_name,

				);

			break;

		case 'tbl_tbl2':

			$requiredColumns = array(...);

			break;

		case 'tbl_tbl3':

			$requiredColumns = array(...);

			break;

	}

}



Thanks everyone, this has been very helpful. Based on your input I changed my strategy but now I’m facing a different problem: http://www.yiiframework.com/forum/index.php?/topic/17188-retrieving-model-attributes-in-behaviour/ . Any suggestions would be much appreciated.