khvalov
(khvalov)
February 25, 2019, 11:00pm
1
I have a requirement to create base controller. On low level I have to execute customized actions based on input JSON, get deal with stdinput and send JSON (and only json) responses. Unformtutaly I can’t do it from WebController layer as actions are executed on level below.
Once I get tried to create own BaseController - yii do not allow to run it because it should be instance of base name space (part of core Yii)
So my question is - what is the best practices here? How I can create baseController to use it as underlayer for WebController?
machour
(Mehdi Achour)
February 25, 2019, 11:03pm
2
Normally you would define a \app\components\BaseController extends \yii\web\controllers
, and then make all your other controllers inherit from it.
But I’m not sure I’m getting your question right.
Coksnuss
(Schanz15)
February 26, 2019, 8:01pm
3
You can achieve that by conditionally executing controller actions via yii\base\Controller::run
Have a look at the guide regarding content negotiation: https://www.yiiframework.com/doc/guide/2.0/en/rest-response-formatting#content-negotiation
What do you mean by that?
Ultimately the following Controller should be sufficient for your needs. If not please go into more detail on what you want to achieve.
<?php
namespace app\controllers;
use Yii;
use yii\web\BadRequestHttpException;
class DispatchController extends \yii\rest\Controller
{
public function actionIndex()
{
$payload = Yii::$app->request->getBodyParams();
if (!isset($payload['action'])) {
throw new BadRequestHttpException();
}
$params = $payload['params'] ?? [];
return $this->run($payload['action'], $params);
}
public function actionTest($echo)
{
return $echo;
}
protected function verbs()
{
return ['index' => ['POST']];
}
}
In order for the above controller to work as expected you need to configure your web application to automatically parse JSON content for you:
config/web.php
// ...
'components' => [
// ...
'request' => [
// ...
'parsers' => [
'application/json' => 'yii\web\JsonParser',
],
],
],
The controller can be used like this:
curl -X POST \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-d '{"action": "test", "params": ["This is passed to Dispatch::actionTest as paramater"] }' \
http://localhost:8080/dispatch`
Response will be
"This is passed to Dispatch::actionTest as paramater"
khvalov
(khvalov)
February 26, 2019, 8:22pm
4
I was under same impression as well, but I faced issue
Invalid Configuration – [yii\base\InvalidConfigException]
Controller class must extend from \yii\base\Controller.
once get tried to create own BaseController