Form Validation Probelm

Hello All,

I am trying to write a file upload feature into my Yii app. The upload works great as long as the user does everything right. My problem occurs if the user does not select a file to upload and hits the submit button. My app crashes. I did some research into this problem and tried just about everything I found but nothing works. I think I must have missed something.

What I would like to happen when a user tries to submit without choosing a file is an error message appears and nothing is submitted to the database.

Any help would be appreciated.

My View Code:


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


echo CHtml::activeFileField($model, 'image');

echo CHtml::hiddenField('herp', 'derp');

echo CHtml::submitButton('Upload');

echo CHtml::endForm(); ?>

My Controller Code:


	/**

	 * Creates a new model.

	 * If creation is successful, the browser will be redirected to the 'view' page.

	 */

	public function actionCreate()

	{

		$model=new File;

        if(isset($_POST['File']))

        {

        	//error_log('isset if');

			

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

            

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

            error_log('IMAGE: '.$model->image); 

            //if($model->save())

            //{

               $user_id=Yii::app()->user->selectedUser->id;

			   

			   //if the user does not have their own directory (by their id) make one for them

			   $folders = scandir(Yii::app()->basePath . '/../assets/Files/');

			   if(!in_array($user_id, $folders)){

			      mkdir(Yii::app()->basePath . '/../assets/Files/'.$user_id);

			   }

			   			   

			   //save the file

               $model->image->saveAs(Yii::app()->basePath . '/../assets/Files/'.$user_id.'/' . $model->image);

               

               //file_name

               $model->file_name = $model->image;

			   

			   

			   //file_hash

			   $f_name = substr($model->image, 0, strpos($model->image, '.'));

			   $ext = substr($model->image, strpos($model->image, '.'));

			   $file_name_hashed = md5($f_name);

			   $file_hashed = $file_name_hashed.$ext;

			   $model->file_hash = $file_hashed;

			   

			   //file_user_id

			   $model->file_user_id = $user_id;

			   

			   

			   ////////////////////////////////////////////////

			   //WHERE ARE WE GOING TO PUT THE DOWNLOAD FILE?//

			   ////////////////////////////////////////////////

			   

			   //url

			   $url = Yii::app()->basePath.DOWNLOAD.'/'.urlencode($file_hashed).USER.urlencode($user_id);

			   $model->file_url = $url;

			   

			    if($model->save()){

			    	error_log("hey its saved");

			    } else {

					error_log("no save");

				}

				

                // redirect to success page

                $this->actionIndex();

            

        }

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

	}

My Model Code:


class File extends CActiveRecord

{

	

	

	public $image;

	

	/**

	 * Returns the static model of the specified AR class.

	 * @param string $className active record class name.

	 * @return File the static model class

	 */

	public static function model($className=__CLASS__)

	{

		return parent::model($className);

	}


	/**

	 * @return string the associated database table name

	 */

	public function tableName()

	{

		return 'pin_file';

	}


	/**

	 * @return array validation rules for model attributes.

	 */

	public function rules()

	{

		// NOTE: you should only define rules for those attributes that

		// will receive user inputs.

		return array(

			array('file_name, file_hash, file_user_id, file_url', 'required'),

			array('file_user_id', 'numerical', 'integerOnly'=>true),

			array('file_name, file_hash, file_url', 'length', 'max'=>255),

			// The following rule is used by search().

			// Please remove those attributes that should not be searched.

			array('file_id, file_name, file_hash, file_user_id, file_url', 'safe', 'on'=>'search'),

			array('image', 'file'),

		);

	}


	/**

	 * @return array relational rules.

	 */

	public function relations()

	{

		// NOTE: you may need to adjust the relation name and the related

		// class name for the relations automatically generated below.

		return array(

		);

	}


	/**

	 * @return array customized attribute labels (name=>label)

	 */

	public function attributeLabels()

	{

		return array(

			'file_id' => 'File',

			'file_name' => 'File Name',

			'file_hash' => 'File Hash',

			'file_user_id' => 'File User',

			'file_url' => 'File Url',

		);

	}


	/**

	 * Retrieves a list of models based on the current search/filter conditions.

	 * @return CActiveDataProvider the data provider that can return the models based on the search/filter conditions.

	 */

	public function search()

	{

		// Warning: Please modify the following code to remove attributes that

		// should not be searched.


		$criteria=new CDbCriteria;


		$criteria->compare('file_id',$this->file_id);

		$criteria->compare('file_name',$this->file_name,true);

		$criteria->compare('file_hash',$this->file_hash,true);

		$criteria->compare('file_user_id',$this->file_user_id);

		$criteria->compare('file_url',$this->file_url,true);


		return new CActiveDataProvider($this, array(

			'criteria'=>$criteria,

		));

	}

}

Thank you

in your model, change this:


public function rules() {

        return array(

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

                // ...

        );

}

Wouldn’t that allow a user to submit the form without uploading a file? I do not want them to be able to do that.

yes, you are right. sorry i missed your point initially.

i don’t have code handy right out of my head, but i believe you need to do some kind of checking around this


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

how about change to this:




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

if (!isset($uploadfile)){

//throw exception here.

}



and btw, I don’t believe it’s good idea to upload file to /assets/ folder since from yii, it’s kind of generated dynamically and could be wrapped out anytime without breaking your app.

my 2 cents.