Yii 1.1: How to upload image(photo), and path entry in database with update functionality

39 followers

I saw many posts that community newbie is confuse in image/photo upload with random name. so I post this topic covering all useful things regarding to image/photo upload(not covering image attribute related functionality)

View :

_form.php file:

..
//form options array...
'htmlOptions' => array(
        'enctype' => 'multipart/form-data',
    ),
...
..
//Other elements
..
..
<div class="row">
        <?php echo $form->labelEx($model,'image'); ?>
        <?php echo CHtml::activeFileField($model, 'image'); ?>  // by this we can upload image
        <?php echo $form->error($model,'image'); ?>
</div>
<?php if($model->isNewRecord!='1'){ ?>
<div class="row">
     <?php echo CHtml::image(Yii::app()->request->baseUrl.'/banner/'.$model->image,"image",array("width"=>200)); ?>  // Image shown here if page is update page
</div>
..
..
Other elements
..
..

.. ..

Model :

just add below line in rules() method in Model

array('image', 'file','types'=>'jpg, gif, png', 'allowEmpty'=>true, 'on'=>'update'), // this will allow empty field when page is update (remember here i create scenario update)

for all others rules you had to give scenario for insert and update as the rule will apply on both page( Insert and Update ) i.e:

array('title, image', 'length', 'max'=>255, 'on'=>'insert,update'),

.. .. Now comes the main part,

Controller :

Create controller will upload image with random name and enter required database entry.

public function actionCreate()
    {
        $model=new Banner;  // this is my model related to table
        if(isset($_POST['Banner']))
        {
            $rnd = rand(0,9999);  // generate random number between 0-9999
            $model->attributes=$_POST['Banner'];
 
            $uploadedFile=CUploadedFile::getInstance($model,'image');
            $fileName = "{$rnd}-{$uploadedFile}";  // random number + file name
            $model->image = $fileName;
 
            if($model->save())
            {
                $uploadedFile->saveAs(Yii::app()->basePath.'/../banner/'.$fileName);  // image will uplode to rootDirectory/banner/
                $this->redirect(array('admin'));
            }
        }
        $this->render('create',array(
            'model'=>$model,
        ));
    }

Now comes the update action,

public function actionUpdate($id)
    {
        $model=$this->loadModel($id);
 
        if(isset($_POST['Banner']))
        {
            $_POST['Banner']['image'] = $model->image;
            $model->attributes=$_POST['Banner'];
 
            $uploadedFile=CUploadedFile::getInstance($model,'image');
 
            if($model->save())
            {
                if(!empty($uploadedFile))  // check if uploaded file is set or not
                {
                    $uploadedFile->saveAs(Yii::app()->basePath.'/../banner/'.$model->image);
                }
                $this->redirect(array('admin'));
            }
 
        }
 
        $this->render('update',array(
            'model'=>$model,
        ));
    }

Above example is Upload image in specific folder and enter require entry in database. On update it will overwrite image in folder and update the data.

Links

Total 20 comments

#19474 report it
Keamu at 2015/07/20 07:42pm
Yii2 update

Can anybody update this functionality using yii2.0.

#19468 report it
OsamaDiab at 2015/07/17 01:21am
create action can be optionally

is there anyway to make create action optionally and update stay updating old files ??

#19435 report it
johnsnails at 2015/07/07 09:43pm
Update for Yii 1.1.16

Hey Guys!

If you are using the most recent 1.1.16, there are some changes to get this working as expected. See: https://raw.githubusercontent.com/yiisoft/yii/1.1.16/CHANGELOG Specifically: - Bug #1257: CFileValidator is no longer unsafe by default to prevent setting arbitrary values. Instead, when no file is uploaded attribute is set to null (marcovtwout)

So, here is what I have done to get it working. Credit to Larry Ullman's book and this post: http://www.yiiframework.com/forum/index.php/topic/63506-how-can-i-update-records-without-adding-same-image-again/page__view__findpost__p__279888

// The most important change perhaps:
// In my model, the ONLY rules I have about my attribute used to store the file name are as follows:
array('name', 'file', 'allowEmpty'=>false, 'types'=>'pdf', 'on'=>'insert'),
array('name', 'file', 'allowEmpty'=>true, 'types'=>'pdf', 'except'=>'insert', 'safe' => false),
 
// In my view I have this (nothing unusual) .
$form=$this->beginWidget('CActiveForm', array(
    'id'=>'user-form',
    'enableAjaxValidation'=>false,
    'htmlOptions' => array(
        'enctype' => 'multipart/form-data',
    )
));
 
// And in the form I have:
echo $form->fileField($model,'name');
 
// In the controller I have:
public function actionCreate()
{
    $model = new User;
 
    if(isset($_POST['User']))
    {
        $model->attributes=$_POST['User'];
        $uploadedFile = CUploadedFile::getInstance($model, "name");
 
        // Always a good idea to give the file a new name not likely to clash with some existing file.
        $fileName = "image-prefix-" . time() . "-" . $uploadedFile->getExtensionName(); 
        $model->name = $fileName;
        if($model->save())
        {
            $fullPath = Yii::app()->basePath . '/../some-folder/' . $fileName;
            $uploadedFile->saveAs($fullPath);
            $this->redirect(array('view','id'=>$model->id));
        }
    }
 
    $this->render('create', array(
        'model' => $model,
    ));
}
 
// Also in the controller I have
public function actionUpdate($id)
{
    $model=$this->loadModel($id);
 
    if(isset($_POST['User']))
    {
        $model->attributes = $_POST['User'];
        $uploadedFile = CUploadedFile::getInstance($model, 'name');
 
        if($model->save()) {
            if($uploadedFile !== null) {
                $fullPath = Yii::app()->basePath . '/../some-folder/' . $model->name;
                $uploadedFile->saveAs($fullPath);
            }
            $this->redirect(array('view','id'=>$model->id));
        }
    }
 
    $this->render('update',array(
        'model'=>$model,
    ));
}
#19080 report it
seventy6ix at 2015/03/09 07:46am
Time instead of random

Combine php date function with rand to create unique number. Eg: (month and day) + (rand)

#18520 report it
razvanphp at 2014/11/09 07:40am
Duplicate files overwritten

As mentioned already,

rand(0,9999);

can return the same number multiple times, and if the filename is also the same, the file will be overwritten. @Mariusz W. solution is one way, or just use some real random generated id like UUID4 or php uniqid()

#17503 report it
kiran sharma at 2014/06/24 01:39am
@vijay p s

Yes, you can use any jQuery extension or core functionality for that..

#17502 report it
vijay p s at 2014/06/24 01:20am
display Image

In this article, the image will be displayed while updating the file. There is any idea to display the image at the time of uploading on create.

#17422 report it
zealotcik at 2014/06/09 01:32pm
resize image
> hi friends. This works great!! I want to resize the image while am uploading. Is that anyway to resize image with the help of this code.

sure you can, just use PHP function

CLICK ME

#17417 report it
vijay p s at 2014/06/09 03:29am
Resizing image

hi friends. This works great!! I want to resize the image while am uploading. Is that anyway to resize image with the help of this code. help me out

#17013 report it
vijay24 at 2014/04/24 04:14am
why allowEmpty on Update??????
public function rules()
    {
        // NOTE: you should only define rules for those attributes that
        // will receive user inputs.
        return array(
 array('social_icon', 'EImageValidator','types'=>'jpg,png,gif', 'width' => 205, 'height' => 163,'dimensionError' => 'minimum image size should be 300*300','on'=>'insert'),
                        array('social_icon', 'EImageValidator', 'types'=>'jpg,png,gif', 'width' => 205, 'height' => 163,'dimensionError' => 'minimum image size should be 300*300','allowEmpty'=>true, 'on'=>'update'),
);
 
}
#16810 report it
Sohrablou at 2014/03/30 05:03pm
CUploadedFile is null

hi

i use this code in ActionUpdate $uploadedFile=CUploadedFile::getInstance($model,'image');

but $uploadedFile is null... plz help me.

#16674 report it
hshfcb at 2014/03/18 05:00am
name

instead random number is the best that use $rnd = $random = date(time());

#12985 report it
Shahcheraghean at 2013/04/25 05:00am
saving 2 or 3 files

when i try your code for insert, it insert 1 record contain filename with random number and 2 record contain just random numbers?

#10394 report it
kiran sharma at 2012/10/25 09:41am
@Giacomo

Ok, so you want to store default.jpg in database and no saveAs function on empty image field.

so, just do following step:

set fileName default.jpg on empty field as

if(empty($uploadedFile))
  $fileName = 'default.jpg';  // write this code below $fileName = "{$rnd}-{$uploadedFile}";

and for saveAs function use below code,

if(!empty($uploadedFile))
   $uploadedFile->saveAs(Yii::app()->basePath.'/../banner/'.$fileName);

I had tested it and working fine... :D

#10349 report it
Giacomo at 2012/10/22 05:12am
Help

Hi, if no image is submitted the page freezes. I've to do something like

if($uploadedFile != null){
     $rnd = rand(0,9999);  
     $fileName = "{$rnd}-{$uploadedFile}"; 
 }else{
      $fileName = 'default.jpg';    
 }

in order to prevent it. Also i've to do the same here

if($model->save())
{    if($uploadedFile != null){
          $uploadedFile->saveAs(Yii::app()->basePath.'/../banner/'.$fileName);
     } 
           $this->redirect(array('admin'));
}

This declaration inside rules

'allowEmpty' => true,'on'=>'insert,update'

should not prevent this error?

Thanks for your help

#9034 report it
kiran sharma at 2012/07/15 02:41am
@kmindi

yes, i think that part was missing. @kmindi, thankx for update.

#9032 report it
kmindi at 2012/07/14 04:11pm
multipart/form-data

I could not get it to work until i added

'htmlOptions' => array(
        'enctype' => 'multipart/form-data',
    ),

to my options array to the form (using EBootstrapActiveForm)

I updated the article to contain that information too ...

#8961 report it
kiran sharma at 2012/07/10 01:06am
@shaan360

@shaan360, its ok if you do not add scenario on update. you specify in model and not specify in model as $model->scenario='update' than its ok, if you specify user define scenario the you have to specify in controller. cheers..

#8954 report it
shaan360 at 2012/07/09 02:31pm
setting the scenario

and dont forget to set the scenario

$model->scenario='update';

#8913 report it
kiran sharma at 2012/07/07 01:14am
@speedlog

@speedlog, yes you rite, but this is just for demo purpose as upload image with random name.

Leave a comment

Please to leave your comment.

Write new article