Yii2 Attach behavior to Application::EVENT_BEFORE_REQUEST - php

I am trying to check for a cookie on Application::EVENT_BEFORE_REQUEST. What I did is overriding the events function from Behavior model and return a custom function checkLanguage on the event that I mentioned above. I am triggering as beforeRequest in my controller ( in first I tried in the backend/config/main.php but it seems that the CheckIfLoggedIn class can't be reached from there ) and the request goes e to the public function events() in the CheckIfLoggedIn class but doesn't go on to the checkLanguage function.
This is my SiteController behaviors:
public function behaviors()
{
return [
'access' => [
'class' => AccessControl::className(),
'rules' => [
[
'actions' => ['login', 'error'],
'allow' => true,
],
[
'actions' => ['logout', 'index', 'language'],
'allow' => true,
'roles' => ['#'],
],
],
],
'verbs' => [
'class' => VerbFilter::className(),
'actions' => [
'logout' => ['post'],
],
],
'as beforeRequest' => [
'class' => 'backend\components\CheckIfLoggedIn'
]
];
}
and CheckIfLoggedIn.php class:
<?php
namespace backend\components;
use yii\base\Behavior;
use yii\web\Application;
class CheckIfLoggedIn extends Behavior
{
public function events()
{
return [
Application::EVENT_BEFORE_REQUEST => "changeLanguage"
];
}
public function changeLanguage()
{
if(\Yii::$app->getRequest()->getCookies()->has('lang')){
\Yii::$app->language = \Yii::$app->getRequest()->getCookies()->getValue('lang');
}
}
}

The thing is you are trying to attach an Application event at controller level inside the behavior whereas the documentation says you should use the Application config .
Make the following updates, remove the events() function from your class.
backend/components/CheckIfLoggedIn.php
namespace backend\components;
use yii\base\Behavior;
class CheckIfLoggedIn extends Behavior
{
public function changeLanguage()
{
if(\Yii::$app->getRequest()->getCookies()->has('lang')){
\Yii::$app->language = \Yii::$app->getRequest()->getCookies()->getValue('lang');
}
}
}
and add the following to the common/config or backend/config if you want it for backend only
'on '.yii\web\Application::EVENT_BEFORE_REQUEST => [
'backend\components\CheckIfLoggedIn','changeLanguage'
] ,
remember to add it at the same level where id or components index is defined like this
return [
'id' => 'app-backend' ,
'on '.yii\web\Application::EVENT_BEFORE_REQUEST => [
'backend\components\CheckIfLoggedIn','changeLanguage'
] ,
For the first try add a die("hello world"); in the start of changeLanguage so you can confirm it is entering the function changeLanguage.
Hope it helps

Related

Why is the empty POST in YII2 after reinstallation?

We developed our own api for mobile applications, which works on the basis of post requests, but after reinstalling the project on a new server, Yii :: $ app-> request-> post () always returns an empty value. At the same time, Yii :: $ app-> request-> getRawBody () contains a value, but I would not want to rewrite all api.
Tell me what could be the problem and which way to dig? Thanks in advance.
Sending through a mobile application or post through RestClient PHPStorm. Returns emptiness always.
public function behaviors()
{
return [
'access' => [
'class' => AccessControl::class,
'only' => ['logout', 'signup'],
'rules' => [
[
'actions' => ['login'],
'allow' => true,
'roles' => ['?'],
],
[
'actions' => ['login'],
'allow' => true,
'roles' => ['#'],
],
],
],
'verbs' => [
'class' => VerbFilter::class,
'actions' => [
'login' => ['post', 'get'],
'token' => ['post', 'get'],
'logout' => ['post', 'get'],
],
],
];
}
public function beforeAction($action) {
$this->enableCsrfValidation = false;
return parent::beforeAction($action);
}
public function actionLogin()
{
return Yii::$app->request->post("username");
}
Could be your request is by get() method
$app->request->get();
After a new reinstallation of the project, the problem resolved by itself. Thanks to all.

Yii 2 Routing all request to invalid request page expect certain actions

I have 2 controllers with some actions, I want to all requests expect those actions in the 2 controllers to be routed to invalid request page, how can I do that?
suppose:
controller1 => action1, action2, action3 allowed
controller2 => action4, action5, action6 allowed
all other requests should be go to bad request page.
Thank you.
Use Access Control, e.g. for controller 1:
public function behaviors()
{
return [
'access' => [
'class' => \yii\filters\AccessControl::className(),
'only' => ['action1', 'action2', 'action3'],
'rules' => [
[
'allow' => true,
],
// everything else is denied
],
],
];
}
As gmc specified you should use Access Control , however you might want to specify the "bad request" page.
public function behaviors()
{
return [
'access' => [
'class' => AccessControl::className(),
'only' => ['action1', 'action2', 'action3'],
'rules' => [
[
'allow' => true,
],
],
'denyCallback' => function($rule, $action) {
return $this->redirect(['controller/action']);
}
],
];
}

Yii2. dektrium/user. Custom controller action redirects to the login page

Problem
Every custom action redirects back to the login page.
My code
I've extended my custom controller from the dektrium\user\controllers\RegistrationController
My web.php
'urlManager' => [
'enablePrettyUrl' => true,
'showScriptName' => false,
'rules' => [
],
],
...
'modules' => [
'user' => [
'class' => 'dektrium\user\Module',
'controllerMap' => [
'registration' => 'app\controllers\user\RegistrationController'
],
],
],
Custom controller
namespace app\controllers\user;
use dektrium\user\controllers\RegistrationController as BaseAdminController;
class RegistrationController extends BaseAdminController
{
public function actionPlan()
{
echo 'Test';
}
}
Overrode methods works good, but each custom action (site.com/user/registration/plan) redirects back to the login page.
If you want change the access control rules you should change properly eg: in your site controller add plan to the rules accessible without authenctication
class SiteController extends Controller
{
/**
* #inheritdoc
*/
public function behaviors()
{
return [
'access' => [
'class' => AccessControl::className(),
'rules' => [
[
'actions' => ['login','plan', 'error'],
'allow' => true,
],
[
'actions' => ['logout', 'index'],
'allow' => true,
'roles' => ['#'],
],
],
],
'verbs' => [
'class' => VerbFilter::className(),
'actions' => [
'logout' => ['post'],
],
],
];
}
see this for more http://www.yiiframework.com/doc-2.0/guide-security-authorization.html
http://www.yiiframework.com/doc-2.0/yii-filters-accesscontrol.html
Another implementation
class SiteController extends Controller
{
/**
* #inheritdoc
*/
public function behaviors()
{
$behaviors = [
'access' => [
'rules' => [
[
'actions' => ['login', 'plan', 'error'],
'allow' => true,
],
],
],
];
return ArrayHelper::merge($behaviors, parent::behaviors());
}
}

How to redirect to a specific method Yii2 (Advanced Template) ?

How to navigate to index method without automatic login in frontend contoller ?
Extends behaviors method in SiteController:
use yii\filters\AccessControl;
public function behaviors()
{
return [
'access' => [
'class' => AccessControl::className(),
'rules' => [
[
'actions' => ['index'],
'allow' => true,
],
[
'allow' => true,
'roles' => ['#'],
],
],
],
];
}
So index action will be available to everyone, instead other pages will require authentication

Close backend with AccessControl

I can trying simple code.
I have an AccessController which having behaviors():
class AccessController extends BackendController
{
public function behaviors()
{
return [
'access' => [
'class' => AccessControl::className(),
'rules' => [
[
'allow' => true,
'roles' => ['#'],
],
]
],
];
}
/*public function init()
{
parent::init();
if( Yii::$app->getUser()->getIsGuest() )
{
return $this->redirect('/auth');
}
return true;
}*/
public function actions()
{
return [
'WysiwygUpload' => [
'class' => WysiwygUpload::className(),
]
];
}
}
AS I understand, if I didn't declare 'only' key, that is mean to all actions and controllers.
But nothing happen: no one error, nothing
Your controller AccessController work only for yourApp/backend/access request not for all controllerAction..
If you want deny the access to guest in AdminController you shuold apply the behavior of AdminController
class AdminController extends Controller
{
public function behaviors()
{
return [
'access' => [
'class' => AccessControl::className(),
'rules' => [
[
'allow' => true,
'roles' => ['#'],
],
]
],
];
}
........
Then when a guest try accessing to yourApp/backend/admin this is not permitted

Categories