use both beforeAction() and behaviors() method in controller in Yii2 - php

I want to use both beforeAction() and behaviors() method in my controller.
If i add beforeAction() method in my code than behaviors() method is not working.
And if i remove beforeAction() method than behaviors() method is working.
I dont want to remove beforeAction() as it is use to disable csrf token for ajax calls.
public function beforeAction($action)
{
if($action->id =='ignore' || $action->id =='accept')
{
$this->enableCsrfValidation = false;
}
return true;
}
And i want to use behaviors() method for authentication.
public function behaviors()
{
return [
'access' => [
'class' => AccessControl::className(),
'only' => ['create','index','update','change','view','page','active','list'],
'rules' => [
[
'actions' => ['create','index','update','change','view','page','active','list'],
'allow' => true,
'roles' => ['#'],
'matchCallback' => function ($rule, $action)
{
echo "string";
die;
},
],
],
'denyCallback' => function ($rule, $action) {
return $this->redirect(Yii::$app->request->baseUrl);
}
],
];
}
Is there any way to use both method in same controller.

public function beforeAction($action)
{
if($action->id =='ignore' || $action->id =='accept')
{
$this->enableCsrfValidation = false;
}
//return true;
return parent::beforeAction($action);
}
you need to return the parent beforeAction()

Related

rewriting url with updating url in yii2

how change this:
site/faq
to this:
site/faq?festival=nouroz98&id=100000&data=information
this is the FestivalRule class
class FestivalRule implements UrlRuleInterface
{
public $pattern;
public $route;
public function createUrl($manager, $route, $params)
{
return [$route, $params];
}
public function parseRequest($manager, $request)
{
if(!empty($request->getQueryParams())){
if($request->getPathInfo() == 'site/faq'){
return [
'site/faq',
$request->getQueryParams()
];
}
}else{
return [
'site/faq',
[
'festival' => 'nouroze99',
'id' => '10000',
'data' => 'from db',
]
];
}
return false;
}
}
this is the urlmanager config:
'rules' => [
[
'class' => 'app\components\FestivalRule',
'pattern' => 'site/faq/<festival:\w+>/<id:\d+>/<data:\w+>',
'route' => 'site/faq',
],
I want if the URL requested without any parameters i changing that with parameters but i can't place the parameters in URL.
all parameters sent but i wanted url changes too (parameters shows in URL)!

Yii2: how to reduce behaviors() db queries when loading controller?

I am getting model object 3 times (Yii2) to load view controller. This makes my page to load slow. How to reduce it?
public function behaviors()
{
return [
'httpCache' => [
'class' => 'yii\filters\HttpCache',
'only' => ['view'],
'lastModified' => function ($action, $params) {
$post = $this->findModel(Yii::$app->request->get('id'));
return strtotime($post->updated);
},
'etagSeed' => function ($action, $params) {
$post = $this->findModel(Yii::$app->request->get('id'));
return serialize([$post->updated, $post->views, $post->comments, Yii::$app->user->isGuest ? 0 : 1]);
}
],
];
}
public function actionView($id)
{
$model = $this->findModel($id);
return $this->render('view', [
'model' => $model,
]);
}
You can cache model instance at controller level:
private $_models = [];
protected function findModel($id) {
if (!array_key_exists($id, $this->_models)) {
$this->_models[$id] = MyModel::findOne($id);
if ($this->_models[$id] === null) {
$this->notFound();
}
}
return $this->_models[$id];
}
Only first call of findModel() will query DB, next calls will return already instantiated object.

"NetworkError: 405 Method Not Allowed" in YII2 rest API

I am working on Yii2 rest API, When I call create action of enquiryontroller then I am getting this error : "NetworkError: 405 Method Not Allowed".
And also I go through YII2 documentation but not able to trace my issue.
Please check and revert, it will be a great help.
Here is controller code that is EnquiryController.php :
<?php
namespace frontend\controllers;
use Yii;
use common\models\Enquiry;
use yii\filters\ContentNegotiator;
use yii\web\Response;
use yii\filters\AccessControl;
use yii\rest\ActiveController;
use yii\filters\auth\HttpBearerAuth;
use yii\filters\VerbFilter;
use yii\data\ActiveDataProvider;
class EnquiryController extends ActiveController
{
/**
* #inheritdoc
*/
public $modelClass = 'common\models\Enquiry';
public $serializer = [
'class' => 'yii\rest\Serializer',
'collectionEnvelope' => 'items',
];
public function behaviors()
{
$behaviors = parent::behaviors();
$behaviors['authenticator'] = [
'class' => HttpBearerAuth::className(),
];
$behaviors['contentNegotiator'] = [
'class' => ContentNegotiator::className(),
'formats' => [
'application/json' => Response::FORMAT_JSON,
],
];
return $behaviors;
}
public function actions()
{
$actions = parent::actions();
// disable the "delete" and "create" actions
unset($actions['create']);
unset($actions['delete'], $actions['view']);
unset($actions['index']);
// customize the data provider preparation with the "prepareDataProvider()" method
return $actions;
}
public function actionCreate()
{
$model = new Enquiry();
return Yii::$app->getRequest()->getBodyParams();
if ($model->load(Yii::$app->getRequest()->getBodyParams(), '') && $model->validate()) {
$model->slug = \common\components\Helper::slugify($model->title);
$model->user_id = Yii::$app->user->id;
$model->save();
//mail functionality
return true;
}
return $model;
}
}
and code in config/main-local.php :
'urlManager' => [
'class' => 'yii\web\UrlManager',
'baseUrl' => $baseUrl,
'enablePrettyUrl' => true,
'showScriptName' => false,
//'enableStrictParsing' => true,
'rules' => [
['class' => 'yii\rest\UrlRule', 'controller' =>['api'], 'pluralize'=>true],
],
],
],
'as access' => [
'class' => 'mdm\admin\components\AccessControl',
'allowActions' => [
'site/*',
'api/login',
'profile/*',
'api/activate-user',
'api/contact',
'home/*',
'post/*',
'pages/*',
'categories/*',
'guestbook/*',
'faq/*',
'news/*',
'events/*',
'enquiry/*',
'partners/*',
'api/signup'// add or remove allowed actions to this list
]
],
Have a look to this guide
// disable the "delete" and "create" actions
unset($actions['delete'], $actions['create']);
because in your code you disable the create, delete, view and index action
public function actions()
{
$actions = parent::actions();
// disable the "delete" and "create" actions ?????
unset($actions['create']); ////????
unset($actions['delete'], $actions['view']); /// ????
unset($actions['index']); ////????
// customize the data provider preparation with the "prepareDataProvider()" method
return $actions;
}

Passing values to multiple views

I've this code for the controller (I'm using the basic template for testing purposes:
use Yii;
use yii\filters\AccessControl;
use yii\web\Controller;
use yii\filters\VerbFilter;
use app\models\LoginForm;
use app\models\ContactForm;
class SiteController extends Controller
{
public function behaviors()
{
return [
'access' => [
'class' => AccessControl::className(),
'only' => ['logout'],
'rules' => [
[
'actions' => ['logout'],
'allow' => true,
'roles' => ['#'],
],
],
],
'verbs' => [
'class' => VerbFilter::className(),
'actions' => [
'logout' => ['post'],
],
],
];
}
public function actions()
{
return [
'error' => [
'class' => 'yii\web\ErrorAction',
],
'captcha' => [
'class' => 'yii\captcha\CaptchaAction',
'fixedVerifyCode' => YII_ENV_TEST ? 'testme' : null,
],
];
}
public function actionIndex()
{
$param = $this->somefunction();
return $this->render('index', [
"param" => $param
]);
}
public function actionLogin()
{
if (!\Yii::$app->user->isGuest) {
return $this->goHome();
}
$model = new LoginForm();
if ($model->load(Yii::$app->request->post()) && $model->login()) {
return $this->goBack();
} else {
return $this->render('login', [
'model' => $model,
]);
}
}
public function actionLogout()
{
Yii::$app->user->logout();
return $this->goHome();
}
public function actionContact()
{
$param = $this->somefunction();
$model = new ContactForm();
if ($model->load(Yii::$app->request->post()) && $model->contact(Yii::$app->params['adminEmail'])) {
Yii::$app->session->setFlash('contactFormSubmitted');
return $this->refresh();
} else {
return $this->render('contact', [
'model' => $model,
"param" => $param
]);
}
}
public function actionAbout()
{
$param = $this->somefunction();
return $this->render('about', [
"param" => $param
]);
}
}
As you can notice, I'm passing param to multiple views with the same content so I want some time-saving way to send it only one time to all views.
Is that possible?
Currently, I'm using the session to store values and call the session in required views. I want something more convenience
You can use Controller and View events to achieve that.
Add this to your controller:
use yii\web\View;
...
public function beforeAction($action)
{
if (!parent::beforeAction($action)) {
return false;
}
$this->view->on(View::EVENT_BEFORE_RENDER, function() {
$this->view->params['param'] = ...;
});
return true;
}
If you want it in multiple controllers, either create another controller (extending from yii\web\Controller) for that and override beforeAction and then extend your controllers from custom one, or set it during application boostrap using BoostrapInterface.
Additionally you can add some condition:
if (in_array($action, ['create', 'update']) {
...
}
and custom param will be only passed in these actions.
in your controller you can redefine the init () function thanks to which you can assign to a variable of the controller the value you're interested

Yii2 Restfull APi RBAC Guest login

I have a rest full API in Yii2. I have the user model, controller and created a new rest action called login.
How can I set the action login to be executed by the guest users?
class UserController extends \yii\rest\ActiveController{
public function actions() {
$actions = parent::actions();
$actions['login'] = [
'class' => 'app\modules\user\actions\user\LoginUserAction',
'modelClass' => $this->modelClass,
'checkAccess' => [$this, 'checkAccess'],
];
return $actions;
}
public function checkAccess($action, $model = null, $params = array()) {
return true;
}
}
You can set the access control rules on the behaviors function of your controller, instead of on the checkAccess property on the action:
public function behaviors()
{
$behaviors = parent::behaviors();
$behaviors['access'] = [
'class' => AccessControl::className(),
'except' => ['login'],
'rules' => [
[
'allow' => true,
'actions' => ['foo', 'foo2'],
'roles' => ['admin'],
]
],
];
return $behaviors;
}
In this example, the access control is applied to all actions except 'login'. I left the rules part so you can have an example of how you make customized rules.

Categories