Use both rest and web Controller in one

Hi everyone :wave:
I’m ArklemX and I’m new using the Yii2 Framework.

I don’t really know where to put this Topic, so please give me a hint if necessary.

I have somewhat a problem.

I need to use both rest controllers ( to make an API ) and normal controllers ( for my web ) in the same application. But, the both of them will make basically the same work. So i wanted to know if it was possible to use the same controller for both web and api purposes.

For example,

i have a PostController which is a rest Controller.

And i want to use him to render a view in certain case.

<?php

namespace frontend\controllers;

use frontend\resource\Post;
use yii\filters\auth\HttpBearerAuth;
use yii\rest\ActiveController;

class PostController extends ActiveController
{
	public $modelClass = Post::class;

	 public function behaviors()
	 {
		 $behaviors =  parent::behaviors();
		 $behaviors['authenticator']['only'] = ['create', 'update', 'delete'];
		 $behaviors['authenticator']['authMethods'] = [
			 HttpBearerAuth::class
		 ];

		 return $behaviors;
	 }


         public function actionIndex()
         : string
         {
             return $this->render('index');
         }


}

Is it possible ? If not, how can i do this in a simple way.

Thanks for your future responses :grin: .

Hi There ! I’m back ! And i think i found a solution.

I discovered that i can override actions function of the ActiveController. :sweat_smile:

Below, we can see that all the basics options are defined as rest actions that will give us some json or xml responses.

**

actions function of the ActiveController

**

    public function actions()
    {
        return [
            'index' => [
                'class' => 'yii\rest\IndexAction',
                'modelClass' => $this->modelClass,
                'checkAccess' => [$this, 'checkAccess'],
            ],
            'view' => [
                'class' => 'yii\rest\ViewAction',
                'modelClass' => $this->modelClass,
                'checkAccess' => [$this, 'checkAccess'],
            ],
            'create' => [
                'class' => 'yii\rest\CreateAction',
                'modelClass' => $this->modelClass,
                'checkAccess' => [$this, 'checkAccess'],
                'scenario' => $this->createScenario,
            ],
            'update' => [
                'class' => 'yii\rest\UpdateAction',
                'modelClass' => $this->modelClass,
                'checkAccess' => [$this, 'checkAccess'],
                'scenario' => $this->updateScenario,
            ],
            'delete' => [
                'class' => 'yii\rest\DeleteAction',
                'modelClass' => $this->modelClass,
                'checkAccess' => [$this, 'checkAccess'],
            ],
            'options' => [
                'class' => 'yii\rest\OptionsAction',
            ],
        ];
    }

So here is what i do. I define a header with (for example) the name api_request .
if it is set, i know that the request is an api call and i use the default behavior of my Controller.
Else, i remove all these default actions and i use the ones i defined (in the example, i render a view) .

Here is my custom actions function

	public function actions()
	{
		$actions = parent::actions();

		if(!Yii::$app->request->headers['api_request']){
			return [];
		}

		return $actions;
	}

In the end , i have this Controller source code :

<?php

namespace frontend\controllers;

use frontend\resource\Post;
use Yii;
use yii\filters\auth\HttpBearerAuth;
use yii\rest\ActiveController;
use yii\web\Controller;

class PostController extends ActiveController
{
	public $modelClass = Post::class;

	public function actions()
	{
		$actions = parent::actions();

		if(!Yii::$app->request->headers['api_request']){
			return [];
		}

		return $actions;
	}

	public function behaviors()
	 {
		 $behaviors =  parent::behaviors();
		 $behaviors['authenticator']['only'] = ['create', 'update', 'delete'];
		 $behaviors['authenticator']['authMethods'] = [
			 HttpBearerAuth::class
		 ];

		 return $behaviors;
	 }

	 public function actionIndex(){
		 $response = Yii::$app->response;
		 $response->format = \yii\web\Response::FORMAT_HTML;

		 return $this->render('index');

	 }


}

For the time being, it works. But i think we can go further.

I’ll close the topic now.
GoodBye.

Using same controller for Web/API is poor design as they work differently
I suggest you create a module for API and the rest be web