Part II - Trying to understand the principles of Yii !

Until now I know that:

  1. protected/index.php -> creates the sigleton App object configured by config/main.php configuration file;

  2. App (by default) diverts the execution flow, calling controllers/SiteController.php script. This redirects to views/site/index.php script as its default action;

Here, starts new doubts !!!

The index.php script mentioned above provides all its content as the value of $content variable that will be replaced in the result of execution of the script views/layouts/main.php.

The views/layouts/main.php files runs as a template layout (like a Prado's way) but I don't (clear) understand the sequence of callings nor instantiations !

Let's review…

What the default controller (main controller): SiteController.php script do ?

Performs the default action, seeking an index.php file in the views/site/ subdirectory?

Who tells to it that existing a layout script?

Why the name of related layout is "main.php"? Where this name has been defined?

TIA

MN.

A user request is resolved into a controller and an action of that controller. At the simplest form, an action is just a method of the controller that is invoked at the user request.

In the action method, we perform some needed logic and then render the results by calling render($viewName).

The view is merely a PHP script referenced via a name. The controller is responsible to map the view name to the concrete PHP script file (based on getViewFile).

The render() method performs an additional task (compared to renderPartial). That is, it also renders a layout view and embeds the normal view rendering result into that layout view using $content.

The name of the layout view is determined based on Yii::app()->layout and CController::layout. The former governs the layout of all controllers, while the latter may be set to specify a different layout for a particular controller. Yii::app()->layout defaults to 'main'.

Like normal view, a layout view is also referenced via a name. The controller is responsible to locate the concrete layout view file via its name (using getLayoutFile). By default, the layout view files are located under protected/views/layouts.

SiteController (or the currently requested controller) will determine which action to perform, and then call that action method (defaults to actionIndex).

In the action method, we call render() method to render a named view, for example, index. There is a mapping from a view name to its corresponding view file. This is based on

Quote

A user request is resolved into a controller and an action of that controller. At the simplest form, an action is just a method of the controller that is invoked at the user request.

Lets say I have a contoller named "News" (i'm now writing a Newspaper CMS). So I want this controller to handle actions like News/europe, News/world … How can I do this without writing action for every possible category because categories are dynamic ? is it possible with yii ?

In this case, you need a URL rule using CUrlManager or Apache rewrite rule to map the second segment to a GET parameter 'category'. In the rule, you can specify such kind of URLs to be mapped to the News controller and the 'view' action.

that doesn't sound very good, my categories are inside a DB. So i want to call a method which checks if this category exists and if so, do some action. What I want is when yii doesnt find aproriate action to call a method so I will be able to parse the request.I found missingAction() method which sounds like what I need, but can't get it work. In my contrller NewController, I've put a method missingAction but I get the following error : Argument 1 passed to NewsController::missingAction() must be an instance of string, string given, called in D:\WebSites\framework\web\CController.php on line 227 and defined.

How did you call missingAction()? What's the relevant code?

excelent points qiang !

Even a small question.

In spite of a specific parameter (configuration), the primary controller will always embed the required view (an actual view), within the default layout (main) right? Thus, acting as a master_content_page like in Prado !?

Is there a way of exchange through 2 distinct layouts ? Let me clarify.

What kind of "variable" (or property) I can test to determine whether the view will be embeded into layout, is the Login view MainPage view (with menus, logged user, news, etc) ?

Could be:

if( Yii::getUser()->isGuest() )

  redirects to Login view

else

  redirects to MainPage

How ? Remember that we are talking about an action of SiteController controller.

TIA

MN.

By setting $this->layout ($this refers to the current controller instance), you can switch to use different layout.

Quote

How did you call missingAction()? What's the relevant code?

In my derived class NewsController I override this method like this:

public function missingAction(string $actionID)

{

//samo logic, parameters setting

//call to the coresponding action

}

the problem is that it never reaches this method.

Your method signature should be the same as the parent class' method.

yes, it works , 10x so much qiang :)

Quote

By setting $this->layout ($this refers to the current controller instance), you can switch to use different layout.

OK, its runs very well (see my code below).



<?php


class SiteController extends CController


{


...


	/**


	 * This is the default 'index' action that is invoked


	 * when an action is not explicitly requested by users.


	 */	 


	public function actionIndex()


	{


		// renders the view file 'protected/views/site: /index.php or /login.php'


		// using the default layout 'protected/views/layouts: /mainLayout.php or /loginLayout.php'


		if( Yii::app()->user->isGuest ) {


			$this->layout = 'loginLayout';


			$form = new LoginForm;


			// collect user input data


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


			{


				$form->attributes=$_POST['LoginForm'];


				// validate user input and redirect to previous page if valid


				if($form->validate())


					$this->redirect(Yii::app()->user->returnUrl);


			}


			// display the login form


			$this->render( 'login', array('form'=>$form) ); //$this->render('login');


		} else {


			// display the main program


			$this->layout = 'mainLayout';


			$this->render('index');


		}


	}


...


Qiang: thanks for a while.

About the "phreak" question (doubt or problem) you say:

"Your method signature should be the same as the parent class' method."

What exactly he could fix in his method signature ?

TIA:

MN