Required either one filed in Yii2 ActiveForm - yii2

I have a form Message
In which there are 2 fields message and file
I want the validator to validate either one of them field as required
Here is what i have done until now but its not working
public function rules()
{
return [
[['sender_id', 'receiver_id'], 'integer'],
[['message'], 'string'],
[['message','file'],'my_required'],
[['is_delivered', 'is_notified', 'is_deleted', 'is_group'], 'boolean'],
[['created_date', 'updated_date'], 'safe'],
[['image'], 'string', 'max' => 500],
[['file'], 'file', 'extensions'=>'jpg, gif, png, pdf'],
];
}
public function my_required($attribute_name, $params)
{
if (empty($this->file)
&& empty($this->message)
) {
$this->addError($attribute_name, Yii::t('user', 'At least 1 of the field must be filled up properly'));
return false;
}
return true;
}
Here is the code of my form
<div class="row">
<p>
<?php $form = ActiveForm::begin(['options'=>['enctype'=>'multipart/form-data','id' => 'message-form']]); ?>
<div class="form-group col-xs-3 col-lg-3">
<?= $form->field($model, 'message')->textarea(['rows' => 6]) ?>
</div>
<div class="form-group col-xs-3 col-lg-3">
<?= $form->field($model, 'file')->fileInput() ?>
<?= $form->field($model, 'keys')->hiddenInput()->label(false); ?>
<div class="form-group">
<?= Html::submitButton('Send',['class' => 'btn btn-danger','data-placement'=>'right','id'=>'sendMessage']) ?>
</div>
</div>
<?php ActiveForm::end(); ?>
</p>
</div>
I also tried to use this but it didnt work as well
public function rules()
{
return [
[['sender_id', 'receiver_id'], 'integer'],
[['message'], 'string'],
[['is_delivered', 'is_notified', 'is_deleted', 'is_group'], 'boolean'],
[['created_date', 'updated_date'], 'safe'],
[['image'], 'string', 'max' => 500],
[['file'], 'file', 'extensions'=>'jpg, gif, png, pdf'],
['file', 'required', 'when' => function($model) {
return empty($model->message);
}],
];
}
I have also tried using inline validation like this
['file', function ($attribute,$model) {
if (empty($model->message)) {
$this->addError($attribute, 'Form must contain a file or message.');
}
}],
But that did not work out either...

Below works perfectly for me:
['clientGroupId', 'required', 'when' => function($model) {
return empty($model->clientId);
}, 'message' => 'Client group or client selection is required'],

Related

Validate checked checkbox quantity

I have a voting form and I would like to validate the minimum and maximum number of candidates that each voter can vote for. These max and min values are stored in the logged user's session. What better way to do it?
MODEL Voto.php
public static function tableName()
{
return 'voto';
}
public function rules()
{
return [
[['eleicao_id', 'candidato_id', 'cargo_id', 'urna_id', 'created'], 'required','message'=> 'Selecione no mínimo 1 candidato!'],
[['eleicao_id', 'cargo_id', 'urna_id'], 'integer'],
[['created','candidato_id'], 'safe'],
[['eleitor_hash'], 'string', 'max' => 255],
];
}
FORM _form_votacao.php
<?php $form = ActiveForm::begin(); ?>
<div class="row">
<?php
$candidato = ArrayHelper::map(candidato::find()
->where(['status' => 1])
->Andwhere(['eleicao_id' => Yii::$app->user->identity->eleicao_id])
->orderBy("nome ASC")
->all(), 'id', 'nome'
);
echo $form->field($model, 'candidato_id')->checkboxList($candidato, [
'class' => 'h4',
'data-toggle' => 'button',
'item' => function($index, $label, $name, $checked, $value) {
return "<label class='col-md-5'><input type='checkbox' {$checked} name='{$name}' value='{$value}'> {$label}</label>";
}])->label(false);
?>
</div>
<br>
<div class="row text-center">
<div class="form-group">
<?= Html::submitButton('Confirmar', ['class' => 'btn btn-success']) ?>
</div>
</div>
<?php ActiveForm::end(); ?>
Note: This list of candidates is dynamic, loads the candidates according to the parameters of the user logged in.
Rules Test UPDATE:
public function rules()
{
return [
['candidato_id', 'validateCandidates','message'=> 'teste'],
];
}
public function validateCandidates($attribute, $params, $validator){
if(count($this->candidato_id) >= 4){ // test with value 4
$this->addError($attribute, 'Error message');
}
}
Create custom validation. Something like this:
Model Voto.php
public function rules()
{
return [
....
['candidato_id', 'validateCandidates'],
....
];
}
public function validateCandidates($attribute, $params, $validator){
if(count($this->candidato_id) < {session_min} and count($this->candidato_id) > {session_max}){
$this->addError($attribute, 'Error message');
}
}

Yii2 create or update user profile

In my basic app, I have a User model and a UserForm model that stores and update the users in the database. Now, I got problem when updating the user profile. It feedbacks 'Successful update!' even though the new data won't save.
My table:
Table name: User
Attributes: id, fname, mname, lname, address, username, auth_key, password_hash, password_reset_token, email, status, created_at, updated_at
My Model:
class UserForm extends Model
{
public $fname;
public $mname;
public $lname;
public $address;
public $username;
public $email;
public $password_hash;
/**
* #inheritdoc
*/
public function rules()
{
return [
['fname', 'required'],
['fname', 'trim'],
['mname', 'trim'],
['lname', 'required'],
['lname', 'trim'],
['address', 'required'],
['address', 'trim'],
['address', 'string', 'max' => 255],
['username', 'trim'],
['username', 'required'],
['username', 'unique', 'targetClass' => '\app\models\User', 'message' => 'This username has already been taken.'],
['username', 'string', 'min' => 4, 'max' => 255],
['email', 'trim'],
['email', 'required'],
['email', 'email'],
['email', 'string', 'max' => 255],
['email', 'unique', 'targetClass' => '\app\models\User', 'message' => 'This email address has already been taken.'],
['password_hash', 'required', 'on' => 'insert'],
['password_hash', 'string', 'min' => 8],
];
}
public function beforeSave($insert) {
if ($insert) {
$this->setPassword($this->password_hash);
} else {
if (!empty($this->password_hash)) {
$this->setPassword($this->password_hash);
} else {
$this->password_hash = (string) $this->getOldAttribute('password_hash');
}
}
return parent::beforeSave($insert);
}
}
My controller:
public function actionUpdate($id)
{
$model = $this->findModel($id);
$model->setAttribute('password_hash', null);
if ($model->load(Yii::$app->request->post()) && $model->save()) {
Yii::$app->session->setFlash('success', Yii::t('app', 'Successful update!'));
return $this->redirect(['overview']);
} else {
return $this->render('update', [
'model' => $model,
]);
}
}
protected function findModel($id) {
if (($model = User::findOne($id)) !== null) {
return $model;
} else {
throw new NotFoundHttpException('The requested page does not exist.');
}
}
My view.php
<?= $form->field($model, 'fname')->textInput(['autofocus' => true])->label('First Name') ?>
<?= $form->field($model, 'mname')->textInput()->label('Middle Name') ?>
<?= $form->field($model, 'lname')->textInput()->label('Last Name') ?>
<?= $form->field($model, 'address')->textInput() ?>
<?= $form->field($model, 'username')->textInput() ?>
<?= $form->field($model, 'email') ?>
<?= $form->field($model, 'password_hash')->passwordInput(['placeholder' => Yii::t('app', 'Password'), 'value' => ''])->label(false) ?>
<div class="form-group">
<?= Html::submitButton($model->isNewRecord ? Yii::t('app', 'Create') : Yii::t('app', 'Update'), ['class' => $model->isNewRecord ? 'btn btn-success' : 'btn btn-primary']) ?>
</div>
<?php ActiveForm::end(); ?>
Some of the steps are from here: yii2 user CRUD create or update with password
Your UserForm is never used. Your findModel() returns User, so all validation and saving is handled by User model - I guess it does not have any validation rules, so $model->load() does not load anything.
You may try to extend your form model from active record model:
class UserForm extends User
And use it in findModel() or create separate method for returning form model:
protected function findFormModel($id) {
if (($model = UserForm::findOne($id)) !== null) {
return $model;
} else {
throw new NotFoundHttpException('The requested page does not exist.');
}
}
Then use this method in your update action. Don't forget to remove old properties from UserForm - they're unnecessary and may break attributes behavior.

Yii2 Automatically Login after Registration

I'm creating a website using yii2 framework. I have a problem in registration. I have a modal in home and it contains the sign up form. Now when i trying to register, Yes it saved successful but it only stay in the modal. Now i want is after registering it will automatically login.
This is my sign up form_:
<div class="row">
<div class="col-lg-12">
<?php yii\widgets\Pjax::begin(['id' => 'sign-up']) ?>
<?php $form = ActiveForm::begin(['id' => 'form-signup', 'options' => ['data-pjax' => true]]); ?>
<div class="row">
<div class="col-sm-6">
<?= $form->field($model, 'role')->dropDownList(['2' => 'User', '1' => 'Encoder', '3' => 'Admin']) ?>
<?= $form->field($model, 'username')->textInput(['placeholder' => 'Username....']) ?>
<?= $form->field($model, 'email')->textInput(['placeholder' => 'Email....']) ?>
<?= $form->field($model, 'password')->passwordInput(['placeholder' => 'Password.....']) ?>
</div>
<div class="col-sm-6">
<?= $form->field($model, 'confirmPassword')->passwordInput(['placeholder' => 'Confirm Password.....']) ?>
<?= $form->field($model, 'first_name')->textInput(['placeholder' => 'First Name....']) ?>
<?= $form->field($model, 'middle_name')->textInput(['placeholder' => 'Middle Name....']) ?>
<?= $form->field($model, 'last_name')->textInput(['placeholder' => 'Last Name....']) ?>
</div>
</div>
<center>
<?= $form->field($model, 'verifyCode')->widget(Captcha::className()) ?>
</center>
<div class="form-group">
<?= Html::submitButton('Signup', ['class' => 'btn btn-primary', 'name' => 'signup-button', 'style' => 'width: 100%; padding: 10px;']) ?>
</div>
<?php ActiveForm::end(); ?>
<?php yii\widgets\Pjax::end() ?>
</div>
</div>
This is my model:
class SignupForm extends Model
{
public $role;
public $username;
public $email;
public $password;
public $first_name;
public $middle_name;
public $last_name;
public $confirmPassword;
public $verifyCode;
public function rules()
{
return [
['role', 'required'],
['username', 'trim'],
['username', 'required'],
['username', 'unique', 'targetClass' => '\common\models\User', 'message' => 'This username has already been taken.'],
['username', 'string', 'min' => 2, 'max' => 20],
['email', 'trim'],
['email', 'required'],
['email', 'email'],
['email', 'string', 'max' => 30],
['email', 'unique', 'targetClass' => '\common\models\User', 'message' => 'This email address has already been taken.'],
['password', 'required'],
['password', 'string', 'min' => 6],
['first_name', 'trim'],
['first_name', 'required'],
['middle_name', 'trim'],
['middle_name', 'required'],
['last_name', 'trim'],
['last_name', 'required'],
['verifyCode', 'captcha'],
['verifyCode', 'required'],
[['confirmPassword'], 'compare', 'compareAttribute' => 'password', 'message' => 'Passwords do not match.'],
];
}
/**
* 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->role = $this->role;
$user->first_name = $this->first_name;
$user->middle_name = $this->middle_name;
$user->last_name = $this->last_name;
return $user->save() ? $user : null;
}
}
This is my controller:
public function actionSignup()
{
$model = new SignupForm();
if ($model->load(Yii::$app->request->post())) {
if ($user = $model->signup()) {
if (Yii::$app->getUser()->login($user)) {
return $this->goHome();
}
}
}
return $this->renderAjax('signup', [
'model' => $model,
]);
}
I don't have any ideas, I think my codes is correct but i don't know why is not working.
UPDATED
When i clicked the button signup it stay only in the modal and when i clicked it again the button the validations is working. It means it saves to database but not automatically login.
you should get the user identity for login
public function actionSignup()
{
$model = new SignupForm();
if ($model->load(Yii::$app->request->post())) {
if ($user = $model->signup()) {
$identity = User::findOne(['username' => $model->$username]);
if (Yii::$app->user->login($identity)) {
return $this->goHome();
}
}
}
return $this->renderAjax('signup', [
'model' => $model,
]);
}
see this for more http://www.yiiframework.com/doc-2.0/guide-security-authentication.html
http://www.yiiframework.com/doc-2.0/yii-web-user.html
I have used below code and its working for me . Its also a standard code for YII2 .Controller Action Code :
public function actionSignup()
{
$model = new SignupForm();
if ($model->load(Yii::$app->request->post())) {
if ($user = $model->signup()) {
$model= \common\models\User::findOne([$user->id]); //you need to get complete model again and pass it to login function
if (Yii::$app->user->login($model) {
return $this->goHome();
}
}
}
return $this->renderAjax('signup', [
'model' => $model,
]);
}
After couple minutes of step by step debug - it works well
//Signup
public function actionSignup()
{
$model = new SignupForm();
if ($model->load(Yii::$app->request->post()) && $model->signup()) { /*Save
to DB first*/
$genmail = $model->email; //get model email value
$identity = User::findOne(['email' => $genmail]); //find user by email
if (Yii::$app->user->login($identity)) { // login user
return $this->redirect('account'); // show accaount page
}
}
return $this->render('signup', [
'model' => $model,
]);
}

Yii2 Confirm Password not working

I am trying to build a signup form, it works fine when I dont use repeat password, it saves to the model, but when I use my repeat password it just does'nt let me save them in the database. My code is below.
SimUser.php file
public function rules()
{
return [
[['user_email', 'user_password_hash','company_id','user_fname', 'user_lname','agree'], 'required'],
['agree','required','requiredValue' => 1, 'message' => ''],
['user_password_hash_repeat', 'compare','compareAttribute' => 'user_password_hash','message' => 'Password don\'t match'],
[['agree'],'safe'],
[['user_password_hash_repeat'],'safe'],
[['user_company', 'user_suspended', 'user_deleted'], 'integer'],
[['user_created'], 'safe'],
[['user_email'], 'string', 'max' => 255],
[['user_password_hash'], 'string', 'max' => 72],
[['user_fname', 'user_lname'], 'string', 'max' => 45],
[['user_auth_key'], 'string', 'max' => 32],
[['user_access_token'], 'string', 'max' => 100],
];
}
My controller action: site/signup
public function actionSignup()
{
$company = new Company();
$company->load(Yii::$app->request->post());
$company->save();
$model = new SimUser();
if ($model->load(Yii::$app->request->post())) {
$model->setPassword($model->user_password_hash);
$model->generateAuthKey();
$model->company_id = $company->company_id;
//var_dump($model); exit();
$model->save();
$model = new LoginForm();
return $this->render('login',[
'model' => $model,
]);
}
return $this->render('signup', [
'model' => $model,
'company' => $company,
]);
}
Here I am saving the comany name in the company model and the others in the user table.
My views file: signup.php
<h1>Sign Up</h1>
<?= $form->field($model, 'user_fname')->textInput(['placeholder'=>'First Name*','class'=>'form-control col-lg-4'])->label(false);?>
<?= $form->field($model, 'user_lname')->textInput(['placeholder'=>'Last Name*','class'=>'form-control col-lg-4'])->label(false); ?>
<?= $form->field($model,'user_email')->textInput(['placeholder'=>'Email*','class'=>'form-control col-lg-4'])->label(false); ?>
<?= $form->field($model, 'user_password_hash')->passwordInput(['placeholder'=>'Password'])->label(false); ?>
<?= $form->field($model, 'user_password_hash_repeat')->passwordInput(['placeholder'=>'Confirm Password*','class'=>'form-control col-lg-4'])->label(false); ?>
<?= $form->field($company, 'company_name')->textInput(['placeholder'=>'Company Name*','class'=>'form-control col-lg-4'])->label(false); ?>
<?php echo $form->field($model, 'agree')->checkbox(); ?>
<div class="form-group">
<?= Html::submitButton('Sign Up', ['class' => 'pull-left padding-0 btn btn-success', 'name' => 'signup-button']) ?>
</div>
The error message for the company doesn't go, it is always there.. attached output as image
Can anyone of you help me solve this issue? Thanks in advance!!
Company.php
*/
public function rules()
{
return [
[['company_name'], 'required'],
[['company_name'], 'string', 'max' => 75],
];
}
In the controller have saved Company in the beginnig itself. So everytime, I load the page It is saving before I could submit it. Hence the error remains as it is.
Code to be changed:
$company = new Company();
$model = new SimUser(['scenario' => SimUser::SCENARIO_REGISTER]);
if ($model->load(Yii::$app->request->post()) && $company->load(Yii::$app->request->post())) {
$company->save();
$model->setPassword($model->user_password_hash);
$model->generateAuthKey();
$model->company_id = $company->company_id;
$model->save();
So 1 issue has been solved.. Unable to solve the confirm password issue! Would be helpful if someone can post what the mistake is?

Yii2 - Upload form error

I need to implement an upload form and I using krajee's FileInput plugin :
http://demos.krajee.com/widget-details/fileinput
this is my form view
<!--modal render for upload-->
<?php
use yii\widgets\ActiveForm;
use kartik\widgets\FileInput;
use yii\helpers\Url;
?>
<div class="row" >
<div class="col-md-4" >
ファイル <label class="label label-warning">必須</label>
</div>
<div class="col-md-8 file-input" bgcolor="#FAFCFF">
<?= FileInput::widget([
'name' => 'file',
'model' => $model,
'options'=>[
'multiple'=>true
],
'pluginOptions' => [
'uploadUrl' => Url::to(['document/upload-file']),
'uploadExtraData' => [
'parent_folder' => "22222",
'parent_id' => 13
],
'maxFileCount' => 10
]
]);
?>
</div>
</div>
when form load it said:
You must set an input type = file for bootstrap-fileinput plugin to
initialize.
Please tell me what wrong?
//Update model rules
public $extensions = [];
public function rules()
{
return [
['file', 'file', 'extensions' => $this->extensions, 'skipOnEmpty' => false, 'checkExtensionByMimeType' => false],
];
}
You need to set id
<?= FileInput::widget([
'id' => 'fileUpload'
'name' => 'file',