How to log in using two different models or switch identification class in yii2?

I want to allow user login from two different models.

config.php

'user' => [ 'identityClass' => 'app\models\User', //one more class here 'enableAutoLogin' => false, 'authTimeout' => 3600*2, ], 

LoginForm.php

  public function rules() { return [ // username and password are both required [['username', 'password'], 'required'], // rememberMe must be a boolean value ['rememberMe', 'boolean'], // password is validated by validatePassword() ['password', 'validatePassword'], ]; } public function validatePassword($attribute, $params) { if (!$this->hasErrors()) { $user = $this->getUser(); if (!$user || !$user->validatePassword($this->password)) { $this->addError($attribute, Yii::t('user', 'Incorrect username or password.')); } } } public function login() { if ($this->validate()) { return Yii::$app->user->login($this->getUser(), $this->rememberMe ? 3600*24*30 : 0); } else { return false; } } public function parentLogin() { // How to validate parent Login? } public function getUser() { if ($this->_user === false) { $this->_user = User::findByUsername($this->username); } return $this->_user; } 

User.php

 class User extends \yii\db\ActiveRecord implements IdentityInterface { public static function tableName() { return 'users'; } public static function findIdentity($id) { return static::findOne($id); } public static function findByUsername($username) { return static::findOne(['user_login_id' => $username]); } 

controller.php

  public function actionLogin() { // Working } public function actionParentLogin() { $model = new LoginForm(); if ($model->load(Yii::$app->request->post()) && $model->parentLogin()) { $parent = ParentLogin::find()->where(['p_username' => $model->p_username])->one(); if($parent){ \Yii::$app->session->set('p_id',$parent->p_id); return $this->redirect(['parent-dashboard']); } else { Yii::$app->getSession()->setFlash('error', Yii::t('site', 'Incorrect username or password.')); } } return $this->render('parent-login', [ 'model' => $model, ]); } 

I do not know how to check the registration of the parent. For many hours I tried to find a workaround, but could not.

I am stuck on Yii::$app->user->login($this->getUser(), $this->rememberMe ? 3600*24*30 : 0); because there are no parent login entries in the user table.

My questions

1) Is it possible to have two identityClass . If so, how?
2) Is it possible to extend the ParentLogin model to User . If so, how to check?

References

How to extend a user class? Configuring the CWebUser Class
User class userIdentity in yii2

+5
source share
2 answers

Joe Miller has a good understanding of the presence of one user class and some logical fields in the user table to test the user's role as an alternative to rbac. But since this is not possible in your situation, here is what I can offer you (this approach has been tested halfway and should be accepted).

Yes, you can have two or more identification classes, but not at the same time. You need to handle switching between identifiers. So first I suggest you change your LoginForm model a LoginForm :

 class LoginForm extends Model { public $username; public $password; public $rememberMe = true; // we added this parameter to handle userModel class // that is responsible for getting correct user public $userModel; private $_user = false; /* all other methods stay same */ /** * Finds user by [[username]] * * @return User|null */ public function getUser() { if ($this->_user === false) { // calling findByUsername method dynamically $this->_user = call_user_func( [$this->userModel, 'findByUsername'], $this->username ); } return $this->_user; } } 

Now in the controller:

 public function actionParentLogin() { $model = new LoginForm(['userModel' => ParentLogin::className()]); // calling model->login() here as we usually do if ($model->load(Yii::$app->request->post()) && $model->login()) { // no need to worry about checking if we found parent it all done polymorphycally for us in LoginForm // here is the trick, since we loggin in via parentLogin action we set this session variable. Yii::$app->session->set('isParent', true); return $this->redirect(['parent-dashboard']); } else { Yii::$app->getSession()->setFlash('error', Yii::t('site', 'Incorrect username or password.')); } } return $this->render('parent-login', [ 'model' => $model, ]); } 

Your parentLogin model must extend the User model to do all this:

 class parentLogin extends User { public static function tableName() { //you parent users table name return 'parent_users'; } public static function findByUsername($username) { return static::findOne(['p_username' => $username]); } } 

Now that you are logged in, you need to process the identifier, because in the configuration you have 'identityClass' => 'app\models\User' . To do this, we can use the bootstrap property:

 //in your config file 'bootstrap' => [ 'log', //component for switching identities 'app\components\IdentitySwitcher' ], 

IdentitySwitcher Class:

 class IdentitySwitcher extends Component implements BootstrapInterface { public function bootstrap($app) { //we set this in parentLogin action //so if we loggin in as a parent user it will be true if ($app->session->get('isParent')) { $app->user->identityClass = 'app\models\ParentLogin'; } } } 
+4
source

** Change, this will not work, you can only have one identification class ** ** Ref https://github.com/yiisoft/yii2/issues/5134 ** I would suggest trying the following - not verified.

In your configuration, add an additional authentication interface as you suggest;

 'user' => [ 'identityClass' => 'app\models\User', 'enableAutoLogin' => false, 'authTimeout' => 3600*2, ], 'parent' => [ 'identityClass' => 'app\models\Parent', 'enableAutoLogin' => false, 'authTimeout' => 3600*2, ], 

Your Parent model can either extend the User model, which will provide the same validation methods as the original User model, or implement IdentityInterface from scratch. Of your column names in the Parent table, I would suggest a second method, since the columns are different from the User table.

Then you will need two loginForms : loginForm and parentLoginForm , since validation is different in each case.

Then, in your controller, you can call up the appropriate login form as needed.

0
source

Source: https://habr.com/ru/post/1241290/


All Articles