About UpdateAction in Controller(file+nonfile)...included file upload and unlink old file...

Dear all,

I am facing a question regarding the updateAction in my controller.

What I need to do:

When the user click to update , he can choose to update the file or not update the file.

If he chooses to update the file, the server will upload the new file and unlink the old one(php_unlink() ).

If he chooses not to update the file, then the server will not change the old file.

Right now, my code can make this work, however, the name, description and other in my model(database) will not be updated…

That is… only the file can be updated…the name, description…create time…will not change at all!!!

I don’t know what’s wrong with that…

Any ideas?


	public function actionUpdate($id)

	{


          	$model=$this->loadModel($id); 

            

		// Uncomment the following line if AJAX validation is needed

		// $this->performAjaxValidation($model);

             if (!Yii::app()->user->isGuest && (Yii::app()->user->id == $model->owner_id)||(Yii::app()->user->id =='1'))

             {

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

		{

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

                        $file=CUploadedFile::getInstance($model,'file');

                        if (!empty($file)){

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

                        }

              

                        else{

                        $model->file=Apples::model()->findByPk($model->id)->path;

                        }

                        

			if($model->save())

                        { 

  $fileSavePath = "uploads/".$model->c_id."/".$model->owner_id."/" ;


                     $filename = preg_replace('/\s+/', '', $model->file);


if(file_exists($fileSavePath.$filename)){


throw new CHttpException(400,'Please do not upload the same file, if it is not, please CHANGE ITS NAME, refresh this page and re-upload it. Thank you! ');

                                        }


                     if (!file_exists ($fileSavePath)){

                    mkdir ($fileSavePath, 0777, true);

                        }  


                   $path='http://www.xxxxxx.com/uploads/'.$model->c_id.'/'.$model->owner_id.'/'.$filename;

 

  $pathold='uploads/'.$model->c_id.'/'.$model->owner_id.'/';

                     

                         if (file_exists ($pathold.$model->filename)){ 

                           unlink($pathold.$model->filename); 

                           }  




			       $model->file->saveAs("uploads/".$model->c_id."/".$model->owner_id."/".$filename); 




                               $model ->path = $path;

                               $model ->filename =$filename;

                               $model ->save();      

        

                              }


				$this->redirect(array('view','id'=>$model->id));

		}


		$this->render('update',array(

			'model'=>$model,

		));

             }

           else {

		throw new CHttpException(403,"Only owner can do the update action.");

	        }


	}

Thanks!!!

your code was messy, clean it up a bit without test. you can give a try




public function actionUpdate($id)

{

	$model=$this->loadModel($id); 


	// Uncomment the following line if AJAX validation is needed

	// $this->performAjaxValidation($model);

	if (!Yii::app()->user->isGuest && (Yii::app()->user->id == $model->owner_id)||(Yii::app()->user->id =='1'))

	{

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

		{

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

			

			$upload_sucess = false;

			$file=CUploadedFile::getInstance($model,'file');

			if ((is_object($file) && get_class($file)==='CUploadedFile')) {

				if(!$file->getHasError()) {

					$upload_sucess = true;

				}

			}

			

			if($upload_sucess)

			{ 

				$fileSavePath = "uploads/".$model->c_id."/".$model->owner_id."/" ;

				$filename = preg_replace('/\s+/', '', $file->getName());

				

				if(file_exists($fileSavePath.$filename)){

					throw new CHttpException(400,'Please do not upload the same file, if it is not, please CHANGE ITS NAME, refresh this page and re-upload it. Thank you! ');

				}


				if (!file_exists ($fileSavePath)){

					mkdir ($fileSavePath, 0777, true);

				}


				//i would save relative path only, not full domain name

				//$path='http://www.xxxxxx.com/uploads/'.$model->c_id.'/'.$model->owner_id.'/'.$filename;

				$path='/uploads/'.$model->c_id.'/'.$model->owner_id.'/'.$filename;


				//if c_id & owner_id not come from user's input, then $pathold === $fileSavePath

				$pathold='uploads/'.$model->c_id.'/'.$model->owner_id.'/';

				

				if (file_exists ($pathold.$model->filename)){ 

					unlink($pathold.$model->filename); 

				}


				$file->saveAs($fileSavePath.$filename);

				

				$model ->path = $path;

				$model ->filename =$filename;

			}

			

			if ($model ->save())

				$this->redirect(array('view','id'=>$model->id));

		}


		$this->render('update',array(

			'model'=>$model,

		));

	}

	else {

		throw new CHttpException(403,"Only owner can do the update action.");

	}

}

Thanks so much for your help…

But this code will not save the uploaded file… not in the database nor in the server.

I know my code is really messy…however, I think the structure is clear… I checked it several times and don’t know where is the error… so weird…

Also, is it possible to only allow "file is empty" ONLY in updateAction but not Create Action?

Again, Thanks so much.

Best,

jiaming

I found the problem.

It’s pretty simple.

I guess it’s something about validation. Because each time if I leave the upload file filed empty,

it will not save.

Instead, if i upload something, it will save properly.

But I don’t want to allowEmpty my file because I don’t want it legal in the create action…any ideas?

Thanks

Put different validation rules for ‘insert’ and ‘update’ scenario, like this (in your Model)


public function rules()

{

    return array(

        …

        array('file', …), // will be checked always

        array('file', …, 'on'=>'insert, update'), // will be checked upon creation and update

        array('file', …, 'on'=>'insert'), // will be checked only upon creation

        array('file', …, 'on'=>'update'), // will be checked only upon update

        …

    )

}

See: Understanding Scenarios

thanks @bennouna’ for the validation part;

@jiaming: just few comments on your code, no offense though

  1. you got the file instance twice, no need



                        $file=CUploadedFile::getInstance($model,'file');

                        if (!empty($file)){

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



  1. $model->save twice also does not make sense

it’s wired…because each time if i add “allowEmpty”=>true,

it gives me a blank page when I do the update acton,…

Hmm my previous post is misleading. You should not use multiple file validation rules unless they are exclusive

See also:

  • This post especially this comment

  • This one also, especially this comment

Thanks… I have read these posts . and I tried:


public function rules() {

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

        // will receive user inputs.

        return array(

            array('title', 'required'),

            array('title', 'length', 'max'=>125),

            array('description', 'safe'),

            array('pdf', 'file','on'=>'insert',

                'types'=> 'pdf',

                'maxSize' => 1024 * 1024 * 10, // 10MB                

                'tooLarge' => 'The file was larger than 10MB. Please upload a smaller file.',                

            ),

            array('pdf', 'file','on'=>'update',

                'allowEmpty' => true,

                'types'=> 'pdf',

                'maxSize' => 1024 * 1024 * 10, // 10MB                

                'tooLarge' => 'The file was larger than 10MB. Please upload a smaller file.',                

            ),

        );

    }



I tried this code, however, this not works for me.

It seems like each time I tried "allowEmpty"=>true,

it gives me the blank page.

Or… it just tells me file can’t be blank…

Would you please see my update controller’s code? I guess there must be some problems…

I also tried @rootbear 's code, but the file will not be uploaded…(not in database+server)

Thanks so much.

Sorry for the trouble I caused…