How to manage password during update user profile in Yii2 - php

I can add user successfully, For Password hashing I am using md5() But when I update user it is giving an error.
Here are the model rules:
public function rules()
{
return [
[['firstname', 'lastname', 'username', 'email', 'role', 'group_user','status'], 'required'],
['email','email'],
[['confirm'], 'compare', 'compareAttribute' => 'password','on'=>'create'],
[['firstname', 'lastname', 'username', 'email', 'password', 'confirm', ], 'string', 'max' => 255],
];
}
In the form i.e. View, I am using following code:
<div class="form-group">
<?php
if($case == 'create') { //this condition called when create user
echo $form->field($model, 'password')->passwordInput([
'maxlength' => true,
'placeholder' => 'Enter the Password',
]);
}
else { // during update
echo $form->field($model, 'password')->passwordInput([
'maxlength' => true,
'placeholder' => 'Enter the Password',
'value' => '',
]);
}
?>
</div>
<div class="form-group">
<?= $form->field($model, 'confirm')->passwordInput([
'maxlength' => true,
'placeholder' => 'Confirm Password',
]) ?>
</div>
and in controller I am using following code:
public function actionUpdate($id)
{
$model = $this->findModel($id);
$case = "update";
if ($model->load(Yii::$app->request->post())) {
$model->save();
return $this->redirect(['view', 'id' => $model->id]);
}
else {
return $this->render('update', [
'model' => $model,
'all_users_array' => $all_users_array,
'all_groups_array' => $all_groups_array,
'case' => $case,
]);
}
}
I am getting the error:
Undefined offset: 1 Failed to prepare SQL: UPDATE xbox_user SET
password=:qp0, role=:qp1, modified=:qp2, status=:qp3 WHERE
id=:qp4
Can anyone please let me what code should be modified there?
Thank you!

It is better to use scenarios in your case and use rules() too for other requirements, In Users.php model file write the following code:
public function scenarios(){
$scenarios = parent::scenarios();
$scenarios['create'] = ['firstname', 'lastname', 'username', 'email', 'role', 'group_user','status', 'password','confirm'];
$scenarios['update'] = ['firstname', 'lastname', 'username', 'email', 'role', 'group_user','status'];
return $scenarios;
}
/**
* #inheritdoc
*/
public function rules()
{
return [
[['firstname', 'lastname', 'username', 'email', 'role', 'group_user','status', 'password','confirm'], 'required'],
['email', 'filter', 'filter' => 'trim'],
['email', 'unique' ],
['email', 'unique' ,'targetAttribute' => 'email'],
['email', 'required'],
['email', 'email'],
['email', 'unique', 'targetClass' => '\common\models\Users', 'message' => 'This email address has already been taken.'],
['confirm', 'compare', 'compareAttribute'=>'password', 'message'=>"Passwords does not match." ],
[['firstname', 'lastname', 'username', 'email', 'password', 'confirm', ], 'string', 'max' => 255],
];
}
In your views file use the following code:
<div class="form-group">
<?php
if($case == 'create'){
echo $form->field($model, 'password')->passwordInput(['maxlength' => true,'placeholder'=>'Enter the Password']);
}
else{
echo $form->field($model, 'password')->passwordInput(['maxlength' => true,'placeholder'=>'Enter the Password']);
}
?>
</div>
<div class="form-group">
<?= $form->field($model, 'confirm')->passwordInput(['maxlength' =>true,'placeholder'=>'Confirm Password']) ?>
</div>
and in your controller file, UsersController.php use the following code:
public function actionUpdate($id)
{
$model = $this->findModel($id);
$model->scenario = 'update'; // calling scenario of update
if ($model->load(Yii::$app->request->post())) {
$req_array = yii::$app->request->post();
$role = $req_array['Users']['role'][0];
$model->role = $role;
if($req_array['Users']['password'] !== $req_array['Users']['confirm'])
{
$model->addError('confirm','Password and Confirm should be same.');
$model->password = $req_array['Users']['password'];
$model->confirm = $req_array['Users']['confirm'];
return $this->render('update', [
'model' => $model,
'all_users_array'=>$all_users_array,
'all_groups_array'=>$all_groups_array,
'case'=>$case,
]);
}
elseif( ($req_array['Users']['password'] == $req_array['Users']['confirm']) && (!empty($req_array['Users']['password'])))
{
$model->password = MD5($req_array['Users']['password']);
$model->save();
return $this->redirect(['view', 'id' => $model->id]);
}
else
{
$model->save();
return $this->redirect(['view', 'id' => $model->id]);
}
} else {
$model->password = '';
return $this->render('update', [
'model' => $model,
'all_users_array'=>$all_users_array,
'all_groups_array'=>$all_groups_array,
'case'=>$case,
]);
}
}
Using this code, you will not get error of required password in update, In case if you fill the password then process of confirm password and required will be run.
Hope this helps for you.

User Model
public function rules()
{
return [
[['firstname', 'lastname', 'username', 'email', 'role', 'group_user','status'], 'required'],
['email','email'],
[['password', 'confirm'], 'required', 'on' => 'create'],
['confirm', 'compare', 'compareAttribute' => 'password', 'message'=>"Passwords does not match." ],
[['firstname', 'lastname', 'username', 'email', 'password', 'confirm', ], 'string', 'max' => 255],
];
}
Update Action
public function actionUpdate($id)
{
$model = $this->findModel($id);
$model->passowrd = '';
$model->confirm = '';
if ($model->load(Yii::$app->request->post())) {
$model->role = $model->role[0];
if (empty($model->password) || empty($model->confirm)) {
$model->password = $model->getOldAttribute('password');
$model->confirm = $model->getOldAttribute('confirm');
}
if ($model->save()) {
return $this->redirect(['view', 'id' => $model->id]);
}
} else {
return $this->render('update', [
'model' => $model,
'all_users_array'=>$all_users_array,
'all_groups_array'=>$all_groups_array,
]);
}
}
Form
<div class="form-group">
<?= $form->field($model, 'password')->passwordInput(['maxlength' => true,'placeholder'=>'Enter the Password']) ?>
</div>
<div class="form-group">
<?= $form->field($model, 'confirm')->passwordInput(['maxlength' => true,'placeholder'=>'Confirm Password']) ?>
</div>

First try this one
[['confirm'], 'compare', 'compareAttribute' => 'password','on'=>'create']
if not work then please follow the following steps create your scenario for updation and don't compare password
Did you try scenarios.. i will give a simple example for user registration and user login i hope it will help you
<?php
class User extends Model
{
public $name;
public $email;
public $password;
public function rules(){
return [
[['name','email','password'],'required'],
['email','email'],
[['name', 'email', 'password'], 'required', 'on' => 'register'],
];
}
public function scenarios()
{
$scenarios = parent::scenarios();
$scenarios['login'] = ['name','password'];//Scenario Values Only Accepted
return $scenarios;
}
}
?>
Apply Scenario For Model
See the below code, We added two ways of setting the scenario of a model. By default, scenario will support the model rules.
<?php
class UserController extends Controller
{
// APPLY SCENARIOS
// scenario is set as a property
public function actionLogin(){
$model = new User;
$model->scenario = 'login';
}
// scenario is set through configuration
public function actionRegister(){
$model = new User(['scenario' => 'register']);
}
}
?>

I have my own basic User model i reuse for most projects, which handles updating new password or leaving the previous one if no password is provided by the update form. Also implements IdentityInterface so it can be used for login to the Application.
My basic User model:
<?php
namespace app\models;
use Yii;
use yii\db\ActiveRecord;
use yii\web\IdentityInterface;
class User extends ActiveRecord implements IdentityInterface {
const SCENARIO_LOGIN = 'login';
const SCENARIO_CREATE = 'create';
const SCENARIO_UPDATE = 'update';
// We use $hash to save the hashed password we already have saved in the DB
public $hash;
public $password_repeat;
/**
* #inheritdoc
*/
public static function tableName() {
return 'user';
}
/**
* #inheritdoc
*/
public function scenarios() {
$scenarios = parent::scenarios();
$scenarios[self::SCENARIO_LOGIN] = ['user', 'password'];
$scenarios[self::SCENARIO_CREATE] = ['user', 'password', 'password_repeat', 'email', 'authKey'];
$scenarios[self::SCENARIO_UPDATE] = ['user', 'password', 'password_repeat', 'email'];
return $scenarios;
}
/**
* #inheritdoc
*/
public function rules() {
return [
[['user'], 'string', 'max' => 45],
[['email'], 'string', 'max' => 45],
[['email'], 'email'],
[['password', 'password_repeat'], 'string', 'max' => 60],
[['authKey'], 'string', 'max' => 32],
[['user', 'password'], 'required', 'on' => self::SCENARIO_LOGIN],
[['user', 'password', 'password_repeat', 'email'], 'required', 'on' => self::SCENARIO_CREATE],
[['user', 'email'], 'required', 'on' => self::SCENARIO_UPDATE],
// Generate a random String with 32 characters to use as AuthKey
[['authKey'], 'default', 'on' => self::SCENARIO_CREATE, 'value' => Yii::$app->getSecurity()->generateRandomString()],
[['password'], 'compare', 'on' => self::SCENARIO_CREATE, 'skipOnEmpty' => true],
[['user'], 'unique'],
];
}
/**
* #inheritdoc
*/
public function attributeLabels() {
return [
'id' => 'Id',
'user' => 'User',
'password' => 'Password',
'authKey' => 'AuthKey',
'email' => 'Email',
];
}
/**
* #inheritdoc
*/
public function beforeSave($insert) {
if (parent::beforeSave($insert)) {
if($insert) {
$this->password = Yii::$app->getSecurity()->generatePasswordHash($this->password);
}
else {
if(strlen($this->password) > 0) {
$this->password = Yii::$app->getSecurity()->generatePasswordHash($this->password);
}
else {
$this->password = $this->hash;
}
}
return true;
}
return false;
}
/**
* #inheritdoc
*/
public function afterFind() {
$this->hash = $this->password;
$this->password = '';
parent::afterFind();
}
/**
* #inheritdoc
*/
public static function findIdentity($id) {
return self::findOne($id);
}
/**
* #inheritdoc
*/
public static function findIdentityByAccessToken($token, $type = null) {
throw new NotSupportedException('"findIdentityByAccessToken" is not implemented.');
}
/**
* #inheritdoc
*/
public static function findByUsername($username) {
$model = static::findOne(['user' => $username]);
return $model;
}
/**
* #inheritdoc
*/
public function getId() {
return $this->getPrimaryKey();
}
/**
* #inheritdoc
*/
public function getAuthKey() {
return $this->authKey;
}
/**
* #inheritdoc
*/
public function validateAuthKey($authKey) {
return $this->authKey === $authKey;
}
/**
* Validates password
*
* #param string $password password to validate
* #return boolean if password provided is valid for current user
*/
public function validatePassword($password) {
return Yii::$app->getSecurity()->validatePassword($password, $this->hash);
}
}
This way you only need to use the corresponding scenario in your create, update and login actions:
$model->scenario = User::SCENARIO_LOGIN;
$model->scenario = User::SCENARIO_CREATE;
$model->scenario = User::SCENARIO_UPDATE;

Related

Always Incorrect username or password.- Yii2

I've installed Yii2 advanced app, I customized the signup according to my user database. After signing up I tried to log in and it says "Incorrect username or password", my password is qwerty also I've checked it many times and it still does not work.
The signup model
class SignupForm extends Model
{
public $username;
public $email;
public $password;
public $first_name;
public $middle_name;
public $last_name;
public $contact;
public $birth_date;
public $type;
public $external_type;
public $status;
public $region_id;
public $barangay_id;
public $province_id;
public $city_municipal_id;
/**
* {#inheritdoc}
*/
public function rules()
{
return [
['username', 'trim'],
['username', 'required'],
['username', 'unique', 'targetClass' => '\common\models\User', 'message' => 'This username has already been taken.'],
['username', 'string', 'min' => 2, 'max' => 255],
['email', 'trim'],
['email', 'required'],
['email', 'email'],
['email', 'string', 'max' => 255],
['email', 'unique', 'targetClass' => '\common\models\User', 'message' => 'This email address has already been taken.'],
['password', 'required'],
['password', 'string', 'min' => 6],
['first_name', 'required'],
['first_name', 'string', 'max' => 45],
['middle_name', 'string', 'max' => 45],
['last_name', 'required'],
['last_name', 'string', 'max' => 45],
['contact', 'required'],
['contact', 'string', 'max' => 11],
['birth_date', 'required'],
['type', 'required'],
['type', 'string', 'max' => 45],
['external_type', 'string', 'max' => 45],
['status', 'string', 'max' => 45],
['region_id', 'required'],
['barangay_id', 'required'],
['province_id', 'required'],
['city_municipal_id', 'required'],
];
}
/**
* Signs user up.
*
* #return User|null the saved model or null if saving fails
*/
public function signup()
{
if (!$this->validate()) {
return null;
}
$user = new User();
$user->username = $this->username;
$user->email = $this->email;
$user->setPassword($this->password);
$user->generateAuthKey();
$user->first_name = $this->first_name;
$user->middle_name = $this->middle_name;
$user->last_name = $this->last_name;
$user->contact = $this->contact;
$user->birth_date = $this->birth_date;
$user->type = $this->type;
$user->external_type = $this->external_type;
$user->status = $this->status;
$user->region_id = $this->region_id;
$user->barangay_id = $this->barangay_id;
$user->province_id = $this->province_id;
$user->city_municipal_id = $this->city_municipal_id;
return $user->save() ? $user : null;
}
}
Where did I get wrong here? It is confusing I think that there's no wrong in my code because I followed the proper installation setup of Yii2 Advanced App.
Login Model
public function login()
{
if ($this->validate()) {
return Yii::$app->user->login($this->getUser(), $this->rememberMe ? 3600 * 24 * 30 : 0);
}
return false;
}
check your user table in phpmyadmin, look at the status column, if this value not equal 10, you can change with 10.
Although you have'nt added the action for the registration or signup, but the point where you are calling the $model->signup() function from the model you must check it inside the if statement and then add a call to \Yii::$app->user->login($userModel); inside, it will log you in after signup.
Your signup() function returns the user model object after inserting the user in the table.
See below code sample
if(($userModel=$model->signUp())!==null){
\Yii::$app->user->login($userModel);
}
Hope it helps you out
Have you tried setting your user model class to implement the identity interface?
First declare your class like so
class MyUser extends ActiveRecord implements IdentityInterface
now somewhere in your class you need to implement these methods
public static function findIdentity($id)
{
return self::findOne(['id'=>$id]);
}
public static function findIdentityByAccessToken($token, $type = null)
{
throw new NotSupportedException("Validation method not supported as of yet.");
}
public function getId()
{
return $this->id;
}
public function getAuthKey()
{
return $this->auth_key;
}
public function validateAuthKey($authKey)
{
return $this->auth_key === $authKey;
}
next go to the components section of you /config/web.php and search for the 'user' component
'user' => [
'identityClass' => 'app\models\MyUser', //<---Your model class
'enableAutoLogin' => true,
],
I think with that your good to go. Let me know if this doesn't work.

Integrity constraint violation – yii\db\IntegrityException Yii2

When I signup and input data username, email and password. Field username is null, i don't know why. And then when I input again data username, email and password the result is error. The description error can see in the picture.
Code for models/User.php :
<?php
namespace app\models;
use Yii;
use yii\web\IdentityInterface;
use yii\db\ActiveRecord;
use yii\behaviors\TimestampBehavior;
class User extends ActiveRecord implements IdentityInterface
{
const STATUS_DELETED = 0;
const STATUS_ACTIVE = 10;
public $id;
public $username;
public $password;
public $authKey;
public $accessToken;
public static function tableName()
{
return '{{%user}}';
}
public function behaviors()
{
return
[
TimestampBehavior::className(),
];
}
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();
}
return $this->render('login', [
'model' => $model,
]);
}
public function actionLogout()
{
Yii::$app->user->logout();
return $this->goHome();
}
public function rules()
{
return
[
['status', 'default', 'value' => self::STATUS_ACTIVE],
['status', 'in', 'range' => [self::STATUS_ACTIVE, self::STATUS_DELETED]],
];
}
/**
private static $users = [
'100' => [
'id' => '100',
'username' => 'admin',
'password' => 'admin',
'authKey' => 'test100key',
'accessToken' => '100-token',
],
'101' => [
'id' => '101',
'username' => 'demo',
'password' => 'demo',
'authKey' => 'test101key',
'accessToken' => '101-token',
],
]; */
/**
* #inheritdoc
*/
public static function findIdentity($id)
{
return static::findOne(['id' => $id, 'status' => self::STATUS_ACTIVE]);
}
/**
* #inheritdoc
*/
public static function findIdentityByAccessToken($token, $type = null)
{
}
/**
* Finds user by username
*
* #param string $username
* #return static|null
*/
public static function findByUsername($username)
{
return static::findOne(['username' => $username, 'status' => self::STATUS_ACTIVE]);
}
/**
* #inheritdoc
*/
public function getId()
{
return $this->getPrimaryKey();
}
/**
* #inheritdoc
*/
public function getAuthKey()
{
return $this->auth_key;
}
/**
* #inheritdoc
*/
public function validateAuthKey($authKey)
{
return $this->getAuthKey() === $authKey;
}
/**
* Validates password
*
* #param string $password password to validate
* #return boolean if password provided is valid for current user
*/
public function validatePassword($password)
{
return Yii::$app->security->validatePassword($password, $this->password_hash);
}
public function generatePasswordResetToken()
{
$this->password_reset_token = Yii::$app->security->generateRandomString() . '_' . time();
}
public function removePasswordResetToken()
{
$this->password_reset_token = null;
}
public function setPassword($password)
{
$this->password_hash = Yii::$app->security->generatePasswordHash($password);
}
public function generateAuthKey()
{
$this->auth_key = Yii::$app->security->generateRandomString();
}
}
Code for models/SignupForm.php :
<?php
namespace app\models;
use app\models\User;
use yii\base\Model;
use Yii;
class SignupForm extends Model
{
public $username;
public $email;
public $password;
public function rules()
{
return
[
['username', 'filter', 'filter' => 'trim'],
['username', 'required'],
['username', 'unique', 'targetClass' => '\app\models\User', 'message' => 'This username has already been
taken.'],
['username', 'string', 'min' => 2, 'max' => 255],
['email', 'filter', 'filter' => 'trim'],
['email', 'required'],
['email', 'email'],
['email', 'string', 'max' => 255],
['email', 'unique', 'targetClass' => '\app\models\User', 'message' => 'This email address has already
been taken'],
['password', 'required'],
['password', 'string', 'min' => 6],
];
}
public function signup()
{
if ($this->validate())
{
$user = new user();
$user->username = $this->username;
$user->email = $this->email;
$user->setPassword($this->password);
$user->generateAuthKey();
if ($user->save())
{
return $user;
}
}
return null;
}
}
Code controllers/siteController.php :
<?php
namespace app\controllers;
use Yii;
use yii\filters\AccessControl;
use yii\web\Controller;
use yii\filters\VerbFilter;
use app\models\LoginForm;
use app\models\ContactForm;
use app\components\AuthHandler;
use app\models\UserSocialMedia;
use app\models\User;
use app\helpers\Url;
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 ? 'testme' : null,
],
'auth' => [
'class' => 'yii\authclient\AuthAction',
'successCallback' => [$this, 'successCallback'],
],
];
}
public function successCallback($client)
{
// call safeAttributes method for properly format data
$attributes = $this->safeAttributes($client);
}
public function safeAttributes($client)
{
// get user data from client
$attributes = $client->getUserAttributes();
// set default value
$safe_attributes = [
'social_media' => '',
'id' => '',
'username' => '',
'name' => '',
'email' => '',
];
// get value from user attributes base on social media
if ($client instanceof \yii\autclient\client\Facebook)
{
$safe_attributes = [
'social_media' => 'facebook',
'id' => $attributes['id'],
'username' => $attributes['email'],
'name' => $attributes['name'],
'email' => $attributes['email'],
];
}
else if ($client instanceof \yii\autclient\client\Google)
{
$safe_attributes = [
'social_media' => 'google',
'id' => $attributes['id'],
'username' => $attributes['emails'] ['0'] ['value'],
'name' => $attributes['displayName'],
'email' => $attributes['emails'] ['0'] ['value'],
];
}
else if ($client instanceof \yii\autclient\client\Twitter)
{
$safe_attributes = [
'social_media' => 'twitter',
'id' => $attributes['id'],
'username' => $attributes['screen_name'],
'name' => $attributes['name'],
'email' => '-',
];
}
else if ($client instanceof \yii\autclient\client\Github)
{
$safe_attributes = [
'social_media' => 'github',
'id' => $attributes['id'],
'username' => $attributes['login'],
'name' => $attributes['name'],
'email' => $attributes['email'],
];
}
return $safe_attributes;
}
public function actionIndex()
{
return $this->render('index');
}
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();
}
return $this->render('login', [
'model' => $model,
]);
}
public function actionLogout()
{
Yii::$app->user->logout();
return $this->goHome();
}
public function actionContact()
{
$model = new ContactForm();
if ($model->load(Yii::$app->request->post()) && $model->contact(Yii::$app->params['adminEmail'])) {
Yii::$app->session->setFlash('contactFormSubmitted');
return $this->refresh();
}
return $this->render('contact', [
'model' => $model,
]);
}
public function actionAbout()
{
return $this->render('about');
}
public function actionCommentary()
{
$model = new \app\models\Commentary();
// return $this->render('commentary',['model' => $model,]);
// Jika form di sumbit dengan method POST
if (Yii::$app->request->post())
{
$model->load(Yii::$app->request->post());
if($model->validate()){
Yii::$app->session->setFlash('success','Thank You');
}
else {
Yii::$app->session->setFlash('error','Sorry, something wrong');
}
return $this->render('result_commentary',['model'=>$model,]);
}
else{
return $this->render('commentary',['model'=>$model,]);
}
}
public function actionQuery()
{
$db = Yii::$app->db;
$command = $db->createCommand('SELECT * FROM employee');
$employees = $command->queryAll();
// Ekstrak data
foreach ($employees as $employee)
{
echo "<br>";
echo $employee['id']." ";
echo $employee['name']." ";
echo $employee['age']." ";
}
}
public function actionQuery2()
{
$db= Yii::$app->db;
// return a single row
$employee = $db->createCommand('SELECT * FROM employee where id=1')
->queryOne();
echo $employee['id']." ";
echo $employee['name']." ";
echo "(".$employee['age'].")";
echo "<hr>";
// return a single column (the first column)
$names = $db->createCommand('SELECT name FROM employee')->
queryColumn();
print_r($names);
echo "<hr>";
// Binding Parameter
$employee = $db->createCommand('SELECT * FROM employee WHERE id=:id'
,['id'=>2])->queryOne();
// INSERT (table name, column values)
//$db->createCommand()->insert('employee',['name'=>'Nur','age'=>'99',
// ])->execute();
// UPDATE (table name, column values, condition)
//$db->createCommand()->update('employee',['age'=>'30'], 'id = 7')
//->execute();
// DELETE (table name, condition)
//$db->createCommand()->delete('employee', 'id = 7')
//->execute();
// table name, column name, column values
$db->createCommand()->batchInsert('employee',
['name', 'age'],
[
['Nur', 25],
['Dani', 32],
['Nurul', 40],
])->execute();
}
public function actionActiveRecord()
{
$employees = \app\models\Employee::find()->all();
foreach($employees as $employee)
{
echo "<br>";
echo $employee->id." ";
echo $employee->name." ";
echo "(".$employee->age.") ";
}
}
public function actionSignup()
{
$model = new \app\models\SignupForm();
// use session
$session = Yii::$app->session;
$attributes = $session['attributes'];
if ($model->load(Yii::$app->request->post()))
{
if ($user = $model->signup())
{
if ($session->has('attributes'))
{
// add data user_social_media
$user_social_media = new UserSocialMedia([
'social_media' => $attributes['social_media'],
'id' => (string)$attributes['id'],
'username' => $attributes['username'],
'user_id' => $user->id,
]);
$user_social_media->save();
}
if (Yii::$app->getUser()->login($user))
{
return $this->goHome();
}
}
}
if ($session->has('attributes'))
{
// set form field with data from social media
$model->username = $attributes['username'];
$model->email = $attributes['email'];
}
return $this->render('signup', ['model' => $model,
]);
}
}
Remove User model attributes' declarations that are present in your database table:
public $id;
public $username;
These will be handled by ActiveRecord and by adding it manually you are preventing this process.

Yii2 Custom Validation function not called

I need to make my custom validation rule to warn the user either email or phone_number field is required , but the custom validation function not called
my code so far :
Model
namespace backend\models;
use Yii;
class Advertisement extends \yii\db\ActiveRecord
{
/**
* #inheritdoc
*/
public static function tableName()
{
return 'advertisement';
}
/**
* #inheritdoc
*/
public function rules()
{
return [
[['position', 'location', 'status'], 'required'],
[['description'], 'string'],
[[ 'phone_number', 'company'], 'integer'],
[['created_at', 'updated_at','date_added'], 'safe'],
[['position', 'email', 'location', ], 'string', 'max' => 255],
[['phone_number','email'], 'myRule'],
];
}
public function myRule($attribute, $params)
{
if (empty($this->email)
&& empty($this->phone_number)
) {
$this->addError($attribute, Yii::t('ap', 'either Phone or Email required'));
return false;
}
return true;
}
/**
* #inheritdoc
*/
public function attributeLabels()
{
return [
'id' => Yii::t('app', 'ID'),
'position' => Yii::t('app', 'Position'),
'description' => Yii::t('app', 'Description'),
'email' => Yii::t('app', 'Email'),
'phone_number' => Yii::t('app', 'Phone Number'),
'created_at' => Yii::t('app', 'Created At'),
'updated_at' => Yii::t('app', 'Updated At'),
'company' => Yii::t('app', 'Company'),
'status' => Yii::t('app', 'Status'),
];
}
/**
* #return \yii\db\ActiveQuery
*/
public function getCompany0()
{
return $this->hasOne(User::className(), ['id' => 'company']);
}
}
controller action
public function actionCreate()
{
$model = new Advertisement();
if ($model->load(Yii::$app->request->post()) ) {
$model->company = Yii::$app->user->identity->id;
$model->created_at = date("Y-m-d H:i:s");
$model->date_added = date("Y-m-d H:i:s");
$model->save();
return $this->redirect(['view', 'id' => $model->id]);
} else {
return $this->render('create', [
'model' => $model,
]);
}
}
any help ?
You need to disable skipOnEmpty property of Validator for it .. For More Info Read
Update your code as
[['phone_number','email'], 'myRule' ,'skipOnEmpty' => false],
I think you hsold use $attribute and not $attribute_name
public function myRule($attribute_name, $params)
{
if (empty($this->email)
&& empty($this->phone_number)
) {
$this->addError($attribute, Yii::t('app', 'either Phone or Email required'));
return false;
}
return true;
}
from yii2 doc
addError() public method Adds an error about the specified attribute
to the model object.
This is a helper method that performs message selection and
internationalization. public void addError ( $model, $attribute,
$message, $params = [] )
Try this action create
public function actionCreate()
{
$model = new Advertisement();
if ($model->load(Yii::$app->request->post()) ) {
if ($model->validate()) {
$model->company = Yii::$app->user->identity->id;
$model->created_at = date("Y-m-d H:i:s");
$model->date_added = date("Y-m-d H:i:s");
$model->save();
return $this->redirect(['view', 'id' => $model->id]);
}
else {
$errors = $model->errors;
return $this->render('create', [
'model' => $model,
]);
}
} else {
return $this->render('create', [
'model' => $model,
]);
}
}

Yii2 Login with database

I have a table in my DB called 'member' where I intend to store username, password and all other related info of a user and I want to use those username/password for login instead yii2's default User.php model. I have been trying for almost a day and modified the Member.php model but can't make it work. Every time I use my custom username/password from db, it says username or password is incorrect.
Can anyone please help me out? Thanks in advance. :)
FYI, I have no such field in member table such as authKey or accessToken. I have tried all the related stackoverflow posts but in vein.
Member.php Model
namespace app\models;
use Yii;
use yii\web\IdentityInterface;
class Member extends \yii\db\ActiveRecord implements IdentityInterface
{
public static function tableName()
{
return 'member';
}
public function rules()
{
return [
[['username', 'password', 'first_name', 'last_name', 'role'], 'required'],
[['created_by_date', 'last_modified_by_date'], 'safe'],
[['username', 'password', 'role', 'created_by_id', 'last_modified_by_id'], 'string', 'max' => 50],
[['first_name', 'last_name', 'middle_name', 'phone', 'mobile'], 'string', 'max' => 100],
[['email'], 'string', 'max' => 250],
[['address_line1', 'address_line2', 'address_line3'], 'string', 'max' => 512]
];
}
public function attributeLabels()
{
return [
'id' => 'ID',
'username' => 'Username',
'password' => 'Password',
'first_name' => 'First Name',
'last_name' => 'Last Name',
'middle_name' => 'Middle Name',
'email' => 'Email',
'phone' => 'Phone',
'mobile' => 'Mobile',
'address_line1' => 'Address Line1',
'address_line2' => 'Address Line2',
'address_line3' => 'Address Line3',
'role' => 'Role',
'created_by_id' => 'Created By ID',
'created_by_date' => 'Created By Date',
'last_modified_by_id' => 'Last Modified By ID',
'last_modified_by_date' => 'Last Modified By Date',
];
}
public static function find()
{
return new MemberQuery(get_called_class());
}
public static function findIdentity($id)
{
$dbUser = self::find()
->where([
"id" => $id
])
->one();
if (!count($dbUser)) {
return null;
}
return new static($dbUser);
}
public static function findIdentityByAccessToken($token, $userType = null)
{
$dbUser = self::find()
->where(["accessToken" => $token])
->one();
if (!count($dbUser)) {
return null;
}
return new static($dbUser);
}
public static function findByUsername($username)
{
$dbUser = self::find()
->where(["username" => $username])
->one();
if (!count($dbUser)) {
return null;
}
return $dbUser;
}
public function getId()
{
return $this->id;
}
public function getAuthKey()
{
return $this->authKey;
}
public function validateAuthKey($authKey)
{
return $this->authKey === $authKey;
}
/**
* Validates password
*
* #param string $password password to validate
* #return boolean if password provided is valid for current user
*/
public function validatePassword($password)
{
return $this->password === $password;
}
}
config/web.php
'user' => [
'identityClass' => 'app\models\Member',
'enableAutoLogin' => true,
],
I didnt change the User.php model. Here it is:
namespace app\models;
class User extends \yii\base\Object implements \yii\web\IdentityInterface
{
private static $users = [
'100' => [
'id' => '100',
'username' => 'admin',
'password' => 'admin',
'authKey' => 'test100key',
'accessToken' => '100-token',
],
'101' => [
'id' => '101',
'username' => 'demo',
'password' => 'demo',
'authKey' => 'test101key',
'accessToken' => '101-token',
],
];
/**
* #inheritdoc
*/
public static function findIdentity($id)
{
return isset(self::$users[$id]) ? new static(self::$users[$id]) : null;
}
/**
* #inheritdoc
*/
public static function findIdentityByAccessToken($token, $type = null)
{
foreach (self::$users as $user) {
if ($user['accessToken'] === $token) {
return new static($user);
}
}
return null;
}
/**
* Finds user by username
*
* #param string $username
* #return static|null
*/
public static function findByUsername($username)
{
foreach (self::$users as $user) {
if (strcasecmp($user['username'], $username) === 0) {
return new static($user);
}
}
return null;
}
/**
* #inheritdoc
*/
public function getId()
{
return $this->id;
}
/**
* #inheritdoc
*/
public function getAuthKey()
{
return $this->authKey;
}
/**
* #inheritdoc
*/
public function validateAuthKey($authKey)
{
return $this->authKey === $authKey;
}
/**
* Validates password
*
* #param string $password password to validate
* #return boolean if password provided is valid for current user
*/
public function validatePassword($password)
{
return $this->password === $password;
}
}
You should make sure you change the getUser() method on models/LoginForm.php to use your Member model class, otherwise it will keep validating against the default User model.
public function getUser() {
if ($this->_user === false) {
$this->_user = Member::findByUsername($this->username);
}
return $this->_user;
}
Also, here is an example of my own User model class
namespace app\models;
use Yii;
class User extends \yii\db\ActiveRecord implements \yii\web\IdentityInterface {
const SCENARIO_LOGIN = 'login';
const SCENARIO_CREATE = 'create';
public static function tableName() {
return 'user';
}
public function scenarios() {
$scenarios = parent::scenarios();
$scenarios[self::SCENARIO_LOGIN] = ['username', 'password'];
$scenarios[self::SCENARIO_CREATE] = ['username', 'password', 'authKey'];
return $scenarios;
}
public function rules() {
return [
[['username', 'email'], 'string', 'max' => 45],
[['email'], 'email'],
[['password'], 'string', 'max' => 60],
[['authKey'], 'string', 'max' => 32],
[['username', 'password', 'email'], 'required', 'on' => self::SCENARIO_CREATE],
[['authKey'], 'default', 'on' => self::SCENARIO_CREATE, 'value' => Yii::$app->getSecurity()->generateRandomString()],
[['password'], 'filter', 'on' => self::SCENARIO_CREATE, 'filter' => function($value) {
return Yii::$app->getSecurity()->generatePasswordHash($value);
}],
[['username', 'password'], 'required', 'on' => self::SCENARIO_LOGIN],
[['username'], 'unique'],
[['email'], 'unique'],
[['authKey'], 'unique'],
];
}
public function attributeLabels() {
return [
'id' => 'Id',
'username' => 'Username',
'password' => 'Password',
'email' => 'Email',
'authKey' => 'authKey',
];
}
public static function findIdentity($id) {
return self::findOne($id);
}
public static function findIdentityByAccessToken($token, $type = null) {
throw new NotSupportedException('"findIdentityByAccessToken" is not implemented.');
}
public static function findByUsername($username) {
return static::findOne(['username' => $username]);
}
public function getId() {
return $this->getPrimaryKey();
}
public function getAuthKey() {
return $this->authKey;
}
public function validateAuthKey($authKey) {
return $this->authKey === $authKey;
}
public function validatePassword($password) {
return Yii::$app->getSecurity()->validatePassword($password, $this->password);
}
}
Make sure the methods from IdentityInterface you implement but don't want to use throw an exception, just like i do on the findIdentityByAccessToken method.
You should extend User class with your Member class and set in main config:
[...]
'modules' => [
'user' => [
'class' => 'member class
'modelMap' => [
'User' => 'app\models\member',
More info: yii 2 : override user model

Calling unknown method: yii\db\ActiveQuery::formName()

I'm trying to learn yii 2.0 by creating a simple form for adding new posts.
Here's the respective method in my SiteController (have also added use app\models\Posts; at the top):
public function actionSave($id=NULL){
if($id = NULL)
$model = new Posts;
else
$model = $this->loadModel($id);
if(isset($_POST['Posts'])){
$model->load($_POST);
if($model->save()){
Yii::$app->session->setFlash('success', 'Model has been saved');
$this->redirect($this->createUrl('site/save', ['id' => $model->id]));
}else
Yii::$app->session->setFlash('error', 'Model could not be saved');
}
echo $this->render('save', ['model' => $model]);
}
It renders save view file. Here's that view file:
<?php
use yii\helpers\Html;
use yii\widgets\ActiveForm;
?>
<?php $form = ActiveForm::begin(['options' => ['class' => 'form-horizontal', 'role' => 'form']]) ?>
<div class="form-group">
<?php echo $form->field($model, 'title')->textInput(['class' => 'form-control']); ?>
</div>
<div class="form-group">
<?php echo $form->field($model, 'data')->textArea(['class' => 'form-control']); ?>
</div>
<?php echo Html::submitButton('Submit', ['class' => 'btn btn-primary pull-right']); ?>
<?php ActiveForm::end();
I'm expecting a form, but it's showing an error Calling unknown method: yii\db\ActiveQuery::formName()
What am i doing wrong here?
public function actionSave($id=NULL){
if($id == NULL)
$model = new Posts;
else
$model = $this->loadModel($id);
if(isset($_POST['Posts'])){
$model->load($_POST);
if($model->save()){
Yii::$app->session->setFlash('success', 'Model has been saved');
//Updated
$this->redirect(['save', 'id' =>$model->id]);
//Remove this
//$this->redirect($this->createUrl('site/save', ['id' => $model->id]));
}else
Yii::$app->session->setFlash('error', 'Model could not be saved');
}
echo $this->render('save', ['model' => $model]);
}
I suppose you use the loadModel function, if so, change this line
$model = Posts::find($id);
to this
$model = Posts::find()->where(['id' => $id])->one();
The error occurs because the object returned by loadModel is a ActiveQuery and the ActiveForm expected a ActiveRecord.
Calling unknown method: frontend\models\SignupForm::save()
SiteController.php
public function actionSignup()
{
$model = new SignupForm();
if ($model->load(Yii::$app->request->post()) && $model->save()) {
$fileName = $model->username;
$model->file =UploadedFile::getInstance($model,'file');
$model->file->saveAs('uploads/'.$fileName.'.'.$model->file->extension );
$model->filePath = 'uploads/'.$fileName.'.'.$model->file->extension ;
$model->save();
return $this->redirect(['view', 'id' => $model->idQuiz]);
//}
// if ($model->load(Yii::$app->request->post())) {
if ($user = $model->signup()) {
if (Yii::$app->getUser()->login($user)) {
return $this->goHome();
}
}
}
return $this->render('signup', [
'model' => $model,
]);
}
signup.php
<?= $form->field($model, 'file')-> fileinput(); ?>
SignupForm.php
<?php
namespace frontend\models;
use common\models\User;
use yii\base\Model;
use Yii;
/**
* Signup form
*/
class SignupForm extends Model
{
public $username;
public $email;
public $password;
public $first_name;
public $last_name;
public $address;
public $state_id;
public $city_id;
public $file;
public $filePath;
/**
* #inheritdoc
*/
public function rules()
{
return [
['username', 'filter', 'filter' => 'trim'],
['username', 'required'],
['first_name', 'required'],
['last_name', 'required'],
['address', 'required'],
['state_id', 'required'],
['city_id', 'required'],
['filePath', 'required'],
['username', 'unique', 'targetClass' => '\common\models\User', 'message' => 'This username has already been taken.'],
['username', 'string', 'min' => 2, 'max' => 255],
['email', 'filter', 'filter' => 'trim'],
['email', 'required'],
['email', 'email'],
['email', 'string', 'max' => 255],
['email', 'unique', 'targetClass' => '\common\models\User', 'message' => 'This email address has already been taken.'],
['password', 'required'],
['password', 'string', 'min' => 6],
];
}
/**
* Signs user up.
*
* #return User|null the saved model or null if saving fails
*/
public function signup()
{
if (!$this->validate()) {
return null;
}
$user = new User();
$user->first_name = $this->first_name;
$user->last_name = $this->last_name;
$user->address = $this->address;
$user->state_id = $this->state_id;
$user->city_id = $this->city_id;
$user->filePath = $this->filePath;
$user->username = $this->username;
$user->email = $this->email;
$user->setPassword($this->password);
$user->generateAuthKey();
return $user->save() ? $user : null;
}
}

Categories