Image Uploading Problem

Hi,

I’m Uploading image according this

Insert works fine but Update posts image field as empty. I don’t have any idea why.

model:


<?php




class Artworks extends CActiveRecord

{

	

	/**

	 * @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('image, state', 'required'),

			array('width, height, price_dollar, price_rial, style_id, theme_id, technic_id, category_id', 'numerical', 'integerOnly'=>true),

			array('state', 'length', 'max'=>16),

			array('state', 'in', 'range'=>$this->getAllowedStateRange()),

			array('create_date', 'safe'),

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

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

			array('id, image, width, height, create_date, state, price_dollar, price_rial, style_id, theme_id, technic_id, category_id', 'safe', 'on'=>'search'),

			// this will allow empty field when page is update (remember here i create scenario update)

			//array('image', 'file','types'=>'jpg, gif, png', 'allowEmpty'=>true, 'on'=>'update'), 

		);

	}


	


	/**

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

	 */

	public function attributeLabels()

	{

		return array(

			'id' => 'ID',

			'image' => 'Image',

			'width' => 'Width',

			'height' => 'Height',

			'create_date' => 'Create Date',

			'state' => 'State',

			'price_dollar' => 'Price Dollar',

			'price_rial' => 'Price Rial',

			'style_id' => 'Style',

			'theme_id' => 'Theme',

			'technic_id' => 'Technic',

			'category_id' => 'Category',

		);

	}


	/**

	 * 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('id',$this->id);

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

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

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

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

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

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

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

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

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

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

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


		return new CActiveDataProvider($this, array(

			'criteria'=>$criteria,

		));

	}

}

controller:


<?php


class ArtworksController extends Controller

{

	/**

	 * @var string the default layout for the views. Defaults to '//layouts/column2', meaning

	 * using two-column layout. See 'protected/views/layouts/column2.php'.

	 */

	public $layout='/layouts/column2';


	/**

	 * @return array action filters

	 */

	public function filters()

	{

		return array(

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

			'postOnly + delete', // we only allow deletion via POST request

		);

	}


	

	/**

	 * Displays a particular model.

	 * @param integer $id the ID of the model to be displayed

	 */

	public function actionView($id)

	{

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

			'model'=>$this->loadModel($id),

		));

	}


	/**

	 * Creates a new model.

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

	 */

	public function actionCreate()

	{

		$model=new Artworks;


		// Uncomment the following line if AJAX validation is needed

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


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

		{

			

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

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

			 // random number + file name

			//$fileName = "{$rnd}-{$uploadedFile}";

			$fileName = "{$uploadedFile}";

			$model->image = $fileName;

			$model->tn_image = 'tn_'.$fileName;

			if($model->save())

			{

				$uploadedFile->saveAs(str_replace('/','\\',$_SERVER['DOCUMENT_ROOT']).DIRECTORY_SEPARATOR.'mnaraghi'.DIRECTORY_SEPARATOR.'arts'.DIRECTORY_SEPARATOR.$fileName);

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

			}	

		}


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

			'model'=>$model,

		));

	}


	/**

	 * Updates a particular model.

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

	 * @param integer $id the ID of the model to be updated

	 */

	public function actionUpdate($id)

	{

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


		// Uncomment the following line if AJAX validation is needed

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


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

		{

			

			//$_POST['Artworks']['image'] = $model->image;

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

			

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

			

			if($model->save())

			{

				if(!empty($uploadedFile))  // check if uploaded file is set or not

				{

				    $uploadedFile->saveAs(str_replace('/','\\',$_SERVER['DOCUMENT_ROOT']).DIRECTORY_SEPARATOR.'mnaraghi'.DIRECTORY_SEPARATOR.'arts2'.$model->image);

				}

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

			}

		}


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

			'model'=>$model,

		));

	}


	/**

	 * Deletes a particular model.

	 * If deletion is successful, the browser will be redirected to the 'admin' page.

	 * @param integer $id the ID of the model to be deleted

	 */

	public function actionDelete($id)

	{

		//Delete file

		unlink(str_replace('/','\\',$_SERVER['DOCUMENT_ROOT']).'\mnaraghi\arts\\'.$this->loadModel($id)->image);

		

		$this->loadModel($id)->delete();


		// if AJAX request (triggered by deletion via admin grid view), we should not redirect the browser

		if(!isset($_GET['ajax']))

			$this->redirect(isset($_POST['returnUrl']) ? $_POST['returnUrl'] : array('admin'));

	}


	/**

	 * Lists all models.

	 */

	public function actionIndex()

	{

		$dataProvider=new CActiveDataProvider('Artworks');

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

			'dataProvider'=>$dataProvider,

		));

	}


	

	/**

	 * Returns the data model based on the primary key given in the GET variable.

	 * If the data model is not found, an HTTP exception will be raised.

	 * @param integer $id the ID of the model to be loaded

	 * @return Artworks the loaded model

	 * @throws CHttpException

	 */

	public function loadModel($id)

	{

		$model=Artworks::model()->findByPk($id);

		if($model===null)

			throw new CHttpException(404,'The requested page does not exist.');

		return $model;

	}


	/**

	 * Performs the AJAX validation.

	 * @param Artworks $model the model to be validated

	 */

	protected function performAjaxValidation($model)

	{

		if(isset($_POST['ajax']) && $_POST['ajax']==='artworks-form')

		{

			echo CActiveForm::validate($model);

			Yii::app()->end();

		}

	}

}

Form:


<?php

/* @var $this ArtworksController */

/* @var $model Artworks */

/* @var $form CActiveForm */

?>


<div class="form">


<?php $form=$this->beginWidget('CActiveForm', array(

	'id'=>'artworks-form',

	'enableAjaxValidation'=>false,

	'htmlOptions' => array(

        'enctype' => 'multipart/form-data',

	),

)); ?>


	<p class="note">Fields with <span class="required">*</span> are required.</p>


	<?php echo $form->errorSummary($model); ?>


	<div class="row">

		<?php echo $form->labelEx($model,'image'); ?>

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

		<?php echo $form->error($model,'image'); ?>

	</div>

	<?php if($model->isNewRecord!='1'){ ?>

	<div class="row">

	<!-- Image shown here if page is update page -->

	<?php

	echo CHtml::image(Yii::app()->request->baseUrl.'/arts/'.$model->image,"image",array("width"=>200));}

	?>  


	


<?php $this->endWidget(); ?>


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

Uncomment this line in your actionUpdate:


//$_POST['Artworks']['image'] = $model->image;

Regards.

I comment out it myself. I don’t wanna override image with existing one. However,when it was comment out it didn’t really override file because model->image ALWAYS is EMPTY after form submitting and I don’t know why.

If you write in your actionUpdate this:




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

var_dump($this->image);



What do you see?

You should see image name.

Regards.

If your point is var_dump($model->image); , it shows existing image name.

I also checked print_r($_POST[‘Artworks’]) as you can guess just image field was empty.

Now As you can see in my model I set a rule to check image emptiness and it always detects image field EMPTY! :blink:

I appreciate you for helping me.

Are you sure that the absolute path to image is right?

The picture exist? It could be that the image is not saved in actionCreate?

Are the permissions set correctly in the image directory?

I do like you and it works fine.

Picture exists. I simply click on ‘choose file’ button and select image and image name appears on the field.

Everything on actionCreate works fine. Everything in both actions are the same approximately but image field submit empty in update. It’s weird.

Directory is OK(it’s working fine in create action). I’m in localhost and windows 7.

Here:




<div class="row">

        <!-- Image shown here if page is update page -->

        <?php

        echo CHtml::image(Yii::app()->request->baseUrl.'/arts/'.$model->image,"image",array("width"=>200));}

        ?>  


        


<?php $this->endWidget(); ?>


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



Missing closing tag </div> for:




<div class="row">

        <!-- Image shown here if page is update page -->

        <?php

        echo CHtml::image(Yii::app()->request->baseUrl.'/arts/'.$model->image,"image",array("width"=>200));}

        ?>  



Could that be?

I’ll write this:




<div class="row">

        <?php

            if(!$model->isNewRecord)                              

            {

                echo CHtml::image(Yii::app()->request->baseUrl.'/dirname/'.

                     $model->image,""

                    );

            }

        ?>

        </div>



Regards.

It was my mistake. Thank you for finding it. But it was not critical in my Uploading problem.

I found the solution a moment ago.

It solved with this code:


public function actionUpdate($id)

	{

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

		

		// Uncomment the following line if AJAX validation is needed

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


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

		{

			

			//$_POST['Artworks']['image'] = $model->image;

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

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

			

			$fileName = "{$uploadedFile}";

			

			$model->image = $fileName;

			

			if($model->save())

			{

				if(!empty($uploadedFile))  // check if uploaded file is set or not

				{

					$uploadedFile->saveAs(str_replace('/','\\',$_SERVER['DOCUMENT_ROOT']).DIRECTORY_SEPARATOR.'mnaraghi'.DIRECTORY_SEPARATOR.'arts'.DIRECTORY_SEPARATOR."images".DIRECTORY_SEPARATOR.$fileName);

					

				}

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

			}

		}


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

			'model'=>$model,

		));

	}

It seems file field doesn’t return anything when submitting form. It just upload the file. Therefor in my actionUpload snip code, $model->image doesn’t set in line $model->attributes=$_POST[‘Artworks’]; and I set it from upload instance. I had been thought rules validation occurs when attributes set But my solution shows it accomplishes when model query executing like ($model->save()) , But I’m still not sure about that.

I need more study to be sure or confirmation of someone more experienced to add [SOLVED] On this topic’s title.

At the end, I really appreciate ‘lagogz’ about his helps.

I’m glad you’ve solved.

I’ve been on Holiday, so it took me so long to answer.