Controller
==========

Controller is one of the key parts of the application. It determines how to handle incoming request and creates a response.

Most often a controller takes HTTP request data and returns HTML, JSON or XML as a response.

Basics
------

Controller resides in application's `controllers` directory is is named like `SiteController.php` where `Site`
part could be anything describing a set of actions it contains.

The basic web controller is a class that extends [[\yii\web\Controller]] and could be very simple:

```php
namespace app\controllers;

use yii\web\Controller;

class SiteController extends Controller
{
	public function actionIndex()
	{
		// will render view from "views/site/index.php"
		return $this->render('index');
	}

	public function actionTest()
	{
		// will just print "test" to the browser
		return 'test';
	}
}
```

As you can see, typical controller contains actions that are public class methods named as `actionSomething`.
The output of an action is what the method returns. The return value will be handled by the `response` application
component which can convert the output to differnet formats such as JSON for example. The default behavior
is to output the value unchanged though.

Routes
------

Each controller action has a corresponding internal route. In our example above `actionIndex` has `site/index` route
and `actionTest` has `site/test` route. In this route `site` is referred to as controller ID while `test` is referred to
as action ID.

By default you can access specific controller and action using the `http://example.com/?r=controller/action` URL. This
behavior is fully customizable. For details refer to [URL Management](url.md).

If controller is located inside a module its action internal route will be `module/controller/action`.

In case module, controller or action specified isn't found Yii will return "not found" page and HTTP status code 404.

> Note: If controller name or action name contains camelCased words, internal route will use dashes i.e. for
`DateTimeController::actionFastForward` route will be `date-time/fast-forward`.

### Defaults

If user isn't specifying any route i.e. using URL like `http://example.com/`, Yii assumes that default route should be
used. It is determined by [[\yii\web\Application::defaultRoute]] method and is `site` by default meaning that `SiteController`
will be loaded.

A controller has a default action. When the user request does not specify which action to execute by using an URL such as
`http://example.com/?r=site`, the default action will be executed. By default, the default action is named as `index`.
It can be changed by setting the [[\yii\base\Controller::defaultAction]] property.

Action parameters
-----------------

It was already mentioned that a simple action is just a public method named as `actionSomething`. Now we'll review
ways that an action can get parameters from HTTP.

### Action parameters

You can define named arguments for an action and these will be automatically populated from corresponding values from
`$_GET`. This is very convenient both because of the short syntax and an ability to specify defaults:

```php
namespace app\controllers;

use yii\web\Controller;

class BlogController extends Controller
{
	public function actionView($id, $version = null)
	{
		$post = Post::find($id);
		$text = $post->text;

		if ($version) {
			$text = $post->getHistory($version);
		}

		return $this->render('view', [
			'post' => $post,
			'text' => $text,
		]);
	}
}
```

The action above can be accessed using either `http://example.com/?r=blog/view&id=42` or
`http://example.com/?r=blog/view&id=42&version=3`. In the first case `version` isn't specified and default parameter
value is used instead.

### Getting data from request

If your action is working with data from HTTP POST or has too many GET parameters you can rely on request object that
is accessible via `\Yii::$app->request`:

```php
namespace app\controllers;

use yii\web\Controller;
use yii\web\HttpException;

class BlogController extends Controller
{
	public function actionUpdate($id)
	{
		$post = Post::find($id);
		if (!$post) {
			throw new HttpException(404);
		}

		if (\Yii::$app->request->isPost)) {
			$post->load($_POST);
			if ($post->save()) {
				$this->redirect(['view', 'id' => $post->id]);
			}
		}

		return $this->render('update', ['post' => $post]);
	}
}
```

Standalone actions
------------------

If action is generic enough it makes sense to implement it in a separate class to be able to reuse it.
Create `actions/Page.php`

```php
namespace \app\actions;

class Page extends \yii\base\Action
{
	public $view = 'index';

	public function run()
	{
		$this->controller->render($view);
	}
}
```

The following code is too simple to implement as a separate action but gives an idea of how it works. Action implemented
can be used in your controller as following:

```php
public SiteController extends \yii\web\Controller
{
	public function actions()
	{
		return [
			'about' => [
				'class' => 'app\actions\Page',
				'view' => 'about',
			],
		];
	}
}
```

After doing so you can access your action as `http://example.com/?r=site/about`.


Action Filters
--------------

Action filters are implemented via behaviors. You should extend from `ActionFilter` to
define a new filter. To use a filter, you should attach the filter class to the controller
as a behavior. For example, to use the `AccessControl` filter, you should have the following
code in a controller:

```php
public function behaviors()
{
    return [
        'access' => [
            'class' => 'yii\web\AccessControl',
            'rules' => [
                ['allow' => true, 'actions' => ['admin'], 'roles' => ['@']],
            ),
        ),
    );
}
```

more TDB

Catching all incoming requests
------------------------------

TDB

See also
--------

- [Console](console.md)
