0

I am using yii2 to build a simple application with a signup feature. Problem is when I render a file input tag using active forms, it render a file input field and a hidden field. The validator then picks the one which is hidden and always says that profile image is required though it saves it in my upload directory and also adds the path to the database but still returns with this error. Thanks for any help.

Here is the code: View:

<?php $form = ActiveForm::begin(['id' => 'form-signup' , 'options' => ['enctype' => 'multipart/form-data']]); ?>

   <?= $form->field($model, 'username') ?>

   <?= $form->field($model, 'email') ?>
   <?= $form->field($model, 'profile_path')->widget(FileInput::classname(), [
                    'options' => ['accept' => 'image/*'],
                ]); ?>
   <?= $form->field($model, 'password')->passwordInput() ?>
   <div class="form-group">
   <?= Html::submitButton('Signup', ['class' => 'btn btn-primary', 'name' => 'signup-button']) ?>
    </div>
<?php ActiveForm::end(); ?>

SignupForm // model class

class SignupForm extends Model
{
    public $username;
    public $email;
    public $password;
    public $profile_path;

/**
 * @inheritdoc
 */
public function rules()
{
    return [
        ['username', 'filter', 'filter' => 'trim'],
        ['username', '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],
        [['profile_path'], 'file', 'skipOnEmpty' => false, 'extensions' => 'png, jpg'],
    ];
}

/**
 * Signs user up.
 *
 * @return User|null the saved model or null if saving fails
 */
public function signup()
{
    if ($this->validate()) {
        $user = new User();
        $user->username = $this->username;
        $user->email = $this->email;
        $user->setPassword($this->password);
        $user->generateAuthKey();
        $user->setProfilePicture($this->profile_path);
        if ($user->save(false)) {
            return $user;
        }
    }

    return null;
}

public function upload()
{
    if ($this->validate()) {
        $this->profile_path->saveAs('uploads/' . $this->profile_path->baseName . date('Y-m-d H:i:s') . '.' . $this->profile_path->extension);
        $this->profile_path = 'uploads/' . $this->profile_path->baseName . '.' . $this->profile_path->extension;

        return true;
    } else {
        return false;
    }
}

}

Output:

<label class="control-label" for="signupform-profile_path">Profile Path</label>
<input type="hidden" value="" name="SignupForm[profile_path]">
<input id="signupform-profile_path" type="file" name="SignupForm[profile_path]">
<p class="help-block help-block-error">Please upload a file.</p>
Jonnny
  • 4,939
  • 11
  • 63
  • 93
Noor Ahmed
  • 1,507
  • 9
  • 14
  • I also got the same issue. Looks like there is a issue in the `FileInput` widget itself. I filed a bug. https://github.com/kartik-v/yii2-widget-fileinput/issues/55 – Mahendran Sakkarai Jan 06 '16 at 08:20
  • I have figured it out why the validation was failing. just use image validation instead of file validation . – Noor Ahmed Jan 06 '16 at 08:24
  • updated code is `['profile_path', 'image', 'extensions' => 'png, jpg', 'minWidth' => 100, 'maxWidth' => 2000, 'minHeight' => 100, 'maxHeight' => 2000, ],` – Noor Ahmed Jan 06 '16 at 08:24

3 Answers3

1

I think you should use different scenario avoiding the validation of input hidden when not necessary.. see this doc for a brief guide

And this is a sample of scenario use

Define the rules and scenarios

<?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

<?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']);
        ..............
    }
}

In login scenario only name and password are required in register scenario name, email and password are required

ScaisEdge
  • 131,976
  • 10
  • 91
  • 107
  • I understand your point but the issue is i have an error in validating the image field itself. When the form is posted two fields are posted for profile picture file input i.e Signup[profile_pic] (which is empty) and Signup[profile_pic] (which contains the image). The validation i applied takes the first one and returns the error though the file is saved in uploads directory and database. – Noor Ahmed Jan 05 '16 at 07:47
  • have you setted the value of the input field properly ?.. check if the contained value is correct, then check if your validation logic is correct and last eval if you need a different scenario for some case.. – ScaisEdge Jan 05 '16 at 07:51
  • I have this rule in model class `[['profile_path'], 'file', 'skipOnEmpty' => false, 'extensions' => 'png, jpg'],` . I am not making use of scenarios. There is only one model for my signup form – Noor Ahmed Jan 05 '16 at 08:15
  • Explain me where is the code for hidden input .. which field is related.. I don't see this code.. (eventually edit/updated your question). – ScaisEdge Jan 05 '16 at 08:20
1

Need set value attribute in hiddenOptions

<?= $form->field($model, 'profile_path')->widget(FileInput::class, ['options' => ['accept' => 'image/*', 'hiddenOptions' => ['value' => $model->profile_path]]]) ?>
-1

Ok guys i figured out that the issue was with the validator i was using. Using image validator instead of file validator solved my problem. Here is the updated code for validation.

['profile_path', 'image', 'extensions' => 'png, jpg',
       'minWidth' => 100, 'maxWidth' => 2000,
       'minHeight' => 100, 'maxHeight' => 2000,
],
Noor Ahmed
  • 1,507
  • 9
  • 14