[Solved] Model Not Getting Validated

I am a newbee; started learning Yii recently.

I am trying to upload an image file selected by the user to the server. I want the user to choose a file and a filename to save the uploaded file with. I have specified the ‘required’ rule in model’s rule() but the form get submitted even when I leave the upload file and/or the filename empty. Here are my files:

Model: UploadForm.php


<?php

class UploadForm extends CFormModel

{

  public $image;

  public $uploadfilename;


  public function rules()

  {

    return array(

      array('image', 'file', 'types'=>'jpg,jpeg,gif,png', 'maxSize'=>30720),

      array('image', 'required'),

      array('uploadfilename','required'),

    );

  }


}


?>

Controller: UploadController.php


<?php

class UploadController extends Controller {

    public  $defaultAction="upload" ;


    public function filters()  {

            return array(

                    'accessControl', // perform access control for CRUD operations

            );

    }


    public function accessRules() {

            /* Access Rules

             *  	Based on user authentication: isGuest() !isGurst, isAdminUser() and isSuperUser()

            **/

            // .... 

  

	}


  public function actionUpload() {

      $model=new UploadForm;

      if(isset($_POST['UploadForm']))   {

            $model->attributes=$_POST['UploadForm'];

               $uploadedImage = CUploadedFile::getInstance($model, 'image');

                // Save Image file in a server folder

                $uploadedImage->saveAs(  $model->uploadfilename);

      }

      $this->render('upload',array('model'=>$model));

  }



View file: Upload.php


<div class="form">

    <?php echo CHtml::form('','post',array('enctype'=>'multipart/form-data')); ?>

    <BR>

    <BR>

        <?php echo CHtml::activeLabel($model,'Product Image'); ?>

            <?php echo CHtml::activeFileField($model, 'image'); ?>


    <BR>

         <div class="row">

		<?php echo CHtml::activeLabel($model,'upload filename'); ?>

		<?php echo CHtml::activeTextField($model,'uploadfilename'); ?>

	</div>    

    

    <BR>

        <?php echo CHtml::submitButton('Upload File Now'); ?>


    <?php echo CHtml::endForm(); ?>


</div><!-- form -->



I would appreciate if someone could explain me why the model is not being validated() before being submitted. If I add $model->validated() in uploadAction, it returns me correct result. Do I need to call $model->validate() or the framework should automatically call it?

You have to call validate explicitly

i would do it like this

if($model->validate())

$uploadedImage = CUploadedFile::getInstance($model, ‘image’);

also you have to save your model explicit (which does a validation first too)

which is also missing

so i would change the code like this:




      if(isset($_POST['UploadForm']))   {

            $model->attributes=$_POST['UploadForm'];

if($model->validate())

{

               $uploadedImage = CUploadedFile::getInstance($model, 'image');

                // Save Image file in a server folder

                $uploadedImage->saveAs(  $model->uploadfilename);

$model->save();

}

      }



but i’m not sure if your other code is working well… i would do a check if saving the image works (problems could be, that your server has no more memory or wrong permissions)

I would just add to @balrok reply…

after saving the image if you issue


$model-save()

you again validate all fields, but that is not needed because you validated them before, so you can use


$model->save(false);

Thank you Mdomba and Balrok for usefull suggestions.

I got it that I need to validate() the model explicitly. (In the blog tutorial, model’s validate() function is never user, may be those models are based on CActiveRecord, whereas this model is based on CFormModel.) Well, I modified my controller as given here:


  public function actionUpload() {

      $model=new UploadForm;

      if(isset($_POST['UploadForm']))   {

            $model->attributes=$_POST['UploadForm'];

            if($model->validate()) {

                $uploadedImage = CUploadedFile::getInstance($model, 'image');

                // Save Image file in a server folder

                $uploadedImage->saveAs(  $model->uploadfilename);

                Yii::app()->user->setFlash('FileUploadSuccess',

                        'File has been uploaded successfully. You may upload another file.');

            } else {

                // model could not be validated

                $uploadedImage = CUploadedFile::getInstance($model, 'image');


                if ( ($uploadedImage->hasError)) {

                   $uploaderror =  " Upload error Code: " .$uploadedImage->error ;

                } else {

                   $uploaderror =  " No Upload error " ;

                }


                $modelErrors = $model->getErrors();

                foreach ($modelErrors as $arrayvalue) {

                    $errorlist .=   implode(",", $arrayvalue);

                }


                Yii::app()->user->setFlash('FileUploadError',

                        'Validation Errors: '.

                        $uploaderror.

                        " model errors:" .   $errorlist

                        );


            }

            $this->refresh();

      }

      $this->render('upload',array('model'=>$model));

  }



The framework is doing validation. It checks for ‘image’ filetype & size, ‘image’ required and ‘uploadfilename’ required. However, the rule ‘image’ required always fails even when I choose the upload file and specify the uploadfilename. For instance, if I choose a file larger than 30720, I get the following message:

[font="Courier New"][size="2"]Validation Errors: No Upload error model errors:The file "Pardeep_2008 151.jpg" is too large. Its size cannot exceed 30720 bytes.,Image cannot be blank.[/size] [/font]

Similarly, if I choose the file of incorrect size, I get a message similar to the following:

[font="Courier New"]

[size="2"]Validation Errors: No Upload error model errors:The file "Yii_test.doc" cannot be uploaded. Only files with these extensions are allowed: jpg, jpeg, gif, png.,Image cannot be blank. [/size][/font]

The error messages clearly indicates that the upload file is being selected and is being uploaded to the server. I don’t know why the validation fails with “Image cannot be blank.” Any thoughts?

Thank you for your help.

If I am not mistaken don’t we usually use this code to tell the image is required ??


array('image', 'file', 'allowEmpty'=>false),

probably because of the


array('image','required')

, causes the error message "Image cannot be blank."

Thanks junxiong. Yes, replacing array(‘image’,‘required’) with array(‘image’, ‘file’, ‘allowEmpty’=>false) solved the problem.

Another question: Some members have suggested that I should also use $model->save() or $model->save(false). If I don’t need to save the $model data, is it okay to skip $model->save()? Currently I don’t use it and I don’t get any error.

if you only want upload image, then skipping $model-save() is no problem. But then, if the user want to change the ‘uploadfilename’, then you need to call $model->save() to update the database. Because if you skipping that one, it only upload file to server, but won’t update the value of ‘uploadfilename’ in database.

Got it. Thank you so much.