Yii - Uploading and saving images

updated:  7-Feb-2013

A simple example of a method to upload and save images.  In this example, I created a "Photo" model that saves caption & alt text info to be displayed with the images.  If you create a similar model using Gii and then apply these changes.

Firstly, you will need to install the image extension (cImageComponent) available from the YiiFrameworks extension library and this extension requires either GD or ImageMagick libraries. Controller: Here, I'm just showing you the create action. obviously, you will also need to code the Update and Delete actions as well.

When uploading photos, I prefer to rename the photo with a randomly generated name and this is included in the UpdatePhoto function below. Also, I crunch photos to a maximum size, this stops users trying to upload their 2500px 21Mb photo! The UpdatePhoto function will also create a thumbnail and store that in a "thumbs" sub-directory.



public function actionCreate()
  {
    $model=new Photos;
    if(isset($_POST['Photos']))
    {
                    $model->attributes=$_POST['Photos'];
                    $myfile = CUploadedFile::getInstance($model,'image');
                    $model->image=$myfile;
                    if($model->save())
                        $this->updatePhoto($model, $myfile);
          $this->redirect('view'.'id'=>$model->id);
    }
        $this->render('create',array(
      'model'=>$model,
    ));
  }
        /*--------------
        * Upload and crunch an image
        ----------------*/
        public function updatePhoto($model, $myfile ) {
           if (is_object($myfile) && get_class($myfile)==='CUploadedFile') {
                $ext = $model->image->getExtensionName();
    //generate a filename for the uploaded image based on a random number
    // but check that the random number has not already been used
                if ($model->filename=='' or is_null($model->filename)) {
                    $model->filename = uniqid(rand(), true) . \'.\' . $ext;
                $model->filename=$filename;
                }
                $model->save();
                $model->image->saveAs($model->getPath());  //model->getPath see below
                $image = Yii::app()->image->load($model->getPath());
    //Crunch the photo to a size set in my System Options Table
    //I hold the max size as 800 meaning to fit in an 800px x 800px square
                $size=$this->getOption('PhotoLarge');
                $image->resize($size[0], $size[0])->quality(75)->sharpen(20);
                $image->save();
    // Now create a thumb - again the thumb size is held in System Options Table
    $size=$this->getOption('PhotoThumb');
                $image->resize($size[0], $size[0])->quality(75)->sharpen(20);
                $image->save($model->getThumbnail()); // or $image->save('images/small.jpg');
                return true;
             } else return false;
        }

View: The view is pretty standard, note the enctype has been changed to multipart. Note also, the function getThumbnail from the photo model which returns the thumbnail image.  the code for this is given below.


     $form=$this->beginWidget('CActiveForm', array( 'enableAjaxValidation'=>true, 'id'=>'formPhoto', 'htmlOptions'=>array('enctype'=>'multipart/form-data', ), ));  Fields with * are required.
     echo $model->getThumbnail();
   echo $form->labelEx($model,'filename');
   echo $form->hiddenField($model, 'id');
   echo $form->hiddenField($model, 'property_id');
   echo CHtml::activeFileField($model, 'image'); // see comments below ?-->
     echo $form->labelEx($model,'caption');
   echo $form->textArea($model,'caption',array('rows'=>6, 'cols'=>50));
     echo $form->labelEx($model,'alt_text');
   echo $form->textField($model,'alt_text',array('rows'=>6, 'cols'=>50));
    echo $form->labelEx($model,'sort_order');
  echo $form->textField($model,'sort_order');
    echo CHtml::submitButton($model->isNewRecord ? 'Create' : 'Save');
  echo CHtml::button('Cancel',array('onclick'=-->"window.parent.$('#cru-dialog').dialog('close');window.parent.$('#cru-frame').attr('src','');"));
    $this->endWidget(); 
<!-- form -->

Model


public function getThumbnail(){
         // here i return the image
            if (!empty($this->filename) && $this->filename!='')
             return CHtml::image($this->getPath(),$this->alt_text,array('width'=>options::model()->getOption('PhotoThumb').'px','max-height'=>options::model()->getOption('PhotoThumb').'px'
         ));
        }
  public function getPath($all=true){
            if (is_null($this->_PhotoPath)) {
                 // I hold the image path and system directory separator in the config/main.php
                 // this is because I develop on a windows server and normally deploy on Linux
                 $this->_PhotoPath=Yii::app()->params['imagePATH'];
                 $this->_PathSep=Yii::app()->params['pathSep'];
            }
            $path=$this->_PhotoPath.$this->_PathSep;
            if ($all) $path.=$this->filename;
            return $path;
        }

edit:  I should have mentioned before that the model has a dummy field to store the bitmap image.  Use a variable definition 'Public $image' and add a validation rule as safe.  This will enable the digital image to be saved in the model by the controller using the line


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


Did you know you can hire me?

I take on projects of all sizes. From Consulting to large Development Projects.

If you're starting a new Yii project and would like some help to get setup and running or you need some help with a particular module or you just need someone to develop the whole dang thing, then just ask ...


Beginning Yii ...

I'm very excited about a new Yii Training course that has just been published.

The course is designed for anyone wanting to learn Yii, whether new to frameworks or converting from another.

Eight chapters, each having five videos of between 3 and 5 minutes, take you through the basics of the Yii Framework, building a web application step-by-step.

Save 40% - introductory offer $20.99 / £13.19 / €16.19 / A$20.99

25 comments

  • chris
    07/02/2013

    Hi Jeremy

    I'm using the Image Extension - see Sparkybarkalot's comments for a few updates which I haven't yet put into the article.

    Thanks
    Chris

  • jdraxler
    07/02/2013

    how are you resizing the image? are you using an extension?

  • daudmukadar
    25/01/2013

    Hi, sparky, is it this image extension used in the tutorial?
    http://www.yiiframework.com/extension/image/

    thanks.

  • chris
    26/12/2012

    Hello Esien


    I would need more information to determine why you are getting a server error.


    Have you got debug enabled? Do you have a trace or other error message?


    Also, checkout Sparkybarkalot\'s comments above as I haven\'t yet updated the article with his feed back.


    Also, check that you have inserted the function correctly and that it is syntax free. Sometimes ampersands, dollars and the php bracket get mis-interpreted on a webpage.

  • facebook_loddofrancesco
    23/12/2012

    Hi Thank you for the share :)
    Now i'm testing. I try to integrate your upload photo function on ControllerPost.php, i'm new on yii and i try to develop with this framework and your blog is very useful

    Thanks again

  • esien_0525
    22/12/2012

    Hi, after i put the function 'uploadPhoto' my page show Server Error. May I know why?

  • chris
    20/12/2012

    Hi Sparky

    Thanks for the feedback - I'll update the tutorial as you suggested.

    many thanks, Chris

  • throwaway2012
    19/12/2012

    A few improvements to your post, but first let me say thanks a bunch for this. It really made my life easier. That's the main thing. A few things:


    1) Nowhere do you mention that the image extension is required to run your code successfully. Couldn't figure out what Yii::app()->image was.. until I finally realized that.


    2) A typo: the the model code you call getURL(), but it's really called getPath().


    3) One more typo: in your controller you call getThumb, but the function name is really getThumbnail()


    4) Just an idea: your file randomizer code and filename check code is pretty lengthy. I just removed all those lines and did this instead which works well for me:


    [code]

    $model->filename = uniqid(rand(), true) . '.' . $ext;

    [/code]


    Thanks again! Got everything working great.

  • twitter_ChrisLozeau
    10/12/2012

    I believe it's in reference to the following line in the controller, if it's of any help:
    $filename=$model->property->ref . '_' . $rnd . '.' . $ext;

  • twitter_ChrisLozeau
    10/12/2012

    Hey, I'm getting this error when I submit the form:

    Property "Photos.property" is not defined.

    Any idea what would be causing that?

    I set up the 'photos' table with your SQL code below, may not have set the property table up correctly though.

    Many thanks.

  • chris
    28/11/2012

    Great, thanks for pointing that out. I will update the tutorial.

  • danijel
    27/11/2012

    Thank Chris

  • danijel
    27/11/2012

    I find the error line 3 in model code : && replace with && a

  • chris
    27/11/2012

    Hi Danijel

    The last code block refers to Line 9 in the Controller code example. However, you must place a dummy property in your Photo model to store the bitmap image, as follows:-

    /**
    * This is the model class for table "photos".
    *
    */
    class Photos extends CActiveRecord
    {

    public $image='';
    /**
    * Returns the static model of the specified AR class.
    * @return Photos the static model class
    */
    public static function model($className=__CLASS__)
    {
    return parent::model($className);
    }
    ....
    }

    In this way, the bitmap image is POSTED directly into the model in line 9 of the controller: $model->attributes=$_POST['Photos'];


    Hope this helps
    Chris

  • danijel
    27/11/2012

    I do everything from this tutorial and I have some error (Parse error: syntax error, unexpected ';' in C:\wamp\www\yii\testdrive\protected\modules\image\ImageModule.php on line 7). Only thing that I don't no where to put in the code is last step ( $model->attributes=$_POST['Photos'];). ? Thank for any help that you can provide to me...

  • chris
    14/05/2012

    Johnvery sorry not to have replied to your last comment. I'm currently away from wifi and just getting connection from time to time.In the Photo model, define this dummy field "Public $image" and for the validation you just need to make sure that it is "safe" - no need for anything strnger as you will not actually be storing it in a database.Chris

  • john_rey1219
    14/05/2012

    hello agian chris, i think i've got it all now, there's this one problem,

    "edit: I should have mentioned before that the model has a dummy field to store the bitmap image. Use a variable definition ‘Public $image’ and add a validation rule as safe. This will enable the digital image to be saved in the model by the controller using the line"

    what certain validation rule is it and where will i put iT?? pls help me on this one, this is the last...


    p.s. thanks for everything, and answering this last question will be very much appreciated, agian thank you very much!

    johnrey

  • john_rey1219
    12/05/2012

    hi chris, so if have already created a table and already use gii to generate model and the controller.
    then i copied the codes and pasted it into its relevant parts just like what you suggested, but when i tried to access the view, it shors an error which is this. :
    Parse error: syntax error, unexpected T_IF in C:\wamp\www\scc_ccs\protected\controllers\UploadController.php on line 20.
    and this error points to this:
    if($model->save()){
    $this->updatePhoto($model, $myfile); ..
    what now?......
    pls. help me..again, sorry if i'm a bother...

  • chris
    11/05/2012

    Hi John

    You say \" ...also copied the model and named it UploadForm.php,\"

    Did you change all references from Photos to UploadForm?

    The easiest way would be to create a Photos table and then use Gii to create the model and controller. Then paste in the code above into the relevant parts. Here is my table structure for Photos,

    [code]
    CREATE TABLE IF NOT EXISTS `photos` (

    `id` int(11) NOT NULL auto_increment,

    `property_id` int(11) NOT NULL,

    `filename` varchar(500) default NULL,

    `caption` text,

    `alt_text` text,

    `sort_order` smallint(6) default NULL,

    PRIMARY KEY (`id`),

    KEY `FK_photos` (`property_id`)

    ) ;

    [/code]

    Chris

  • john_rey1219
    11/05/2012

    Ok, so i copied all this codes here, copied the code for the controller and paste it at my web's UserController.php, also copied the model and named it UploadForm.php,

    $this->_PhotoPath=Yii::app()->params['imagePATH'];

    $this->_PathSep=Yii::app()->params['pathSep'];

    i also changed the imagePATH and pathSep to what i had written on my config/main which is this: 'params'=>array(

    // this is used in contact page

    'adminEmail'=>'webmaster@example.com',

    'imagePATH'=>'/scc_ccs/images/Uploads',

    'pathSep'=>'/scc_ccs/images/Uploads',


    now at the VIEW, i copied it just as it is here, i didn't change anything,.. but when i tried to view it, the browser says, Undefined variable: model and it points to this: getThumbnail(); ?>



    I don't kwon if i'm doing it right you know because i'm really new to this, :) ....

    hope you could help me,

    thanks!..

  • chris
    10/05/2012

    Hi John

    Are you sure that you have defined the getThumbnail function as described in your Photo model? You will also need to define local variables in your model (I forgot to mention this) for _PhotoPath and _PathSep.

    You can send me samples of your code if you need more help, either by email or skype userid "chris-backhouse.com"

    Chris

  • john_rey1219
    10/05/2012

    hi, good day, i'm new to yii framework and i have encountered a problem because it seemed that the getThumbnail model in the VIEW is unidentified. what do i do?

  • chris
    06/04/2012

    Hi Tihanyi,

    The params parameter is just like any other in the config as follows:-

    return array(
    'basePath' => $protectedPath,
    'runtimePath' => $runtimePath,
    'name'=>'Website Name',
    'sourceLanguage' => 'en_gb',
    'language' => 'en_gb',
    'theme'=>'default',
    // preloading 'log' component
    'preload'=>array('log','input'),
    'defaultController' => 'user/login',
    params'=>array(
    // this is used in contact page
    'adminEmail'=>'webmaster@example.com',
    'imagePATH'=>'/path/to/images',
    'pathSep'=>'/path/to/somewhere',
    ),
    // application components
    'components'=>array(
    ...........
    ),
    );
    I hope that helps.
    Chris

    PS: Sorry about the font colors - should be fixed now.

  • tihanyil73
    06/04/2012

    Anyway, it does not matter. So I need help configuring the params options in the config/main.php file. So it looks like this: 'params'=>array(

    // this is used in contact page

    'adminEmail'=>'webmaster@example.com',

    'imagePATH'=>'/path/to/images',

    'pathSep'=>'/path/to/somewhere',

    ), And the tutorial looks really great! Thanks

  • tihanyil73
    06/04/2012

    Hi, i need help but before that please change these inputs fontcolor, because i cannot see what i type

Leave a Comment

twitterfacebookgooglelinkedin https://me.yahoo.com