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.
| PHP | | copy code | | ? |
| 01 | |
| 02 | |
| 03 | public function actionCreate() |
| 04 | { |
| 05 | $model=new Photos; |
| 06 | |
| 07 | if(isset($_POST['Photos'])) |
| 08 | { |
| 09 | $model->attributes=$_POST['Photos']; |
| 10 | $myfile = CUploadedFile::getInstance($model,'image'); |
| 11 | $model->image=$myfile; |
| 12 | |
| 13 | if($model->save()) |
| 14 | $this->updatePhoto($model, $myfile); |
| 15 | |
| 16 | $this->redirect('view'.'id'=>$model->id); |
| 17 | } |
| 18 | |
| 19 | $this->render('create',array( |
| 20 | 'model'=>$model, |
| 21 | )); |
| 22 | } |
| 23 | |
| 24 | /*-------------- |
| 25 | * Upload and crunch an image |
| 26 | ----------------*/ |
| 27 | public function updatePhoto($model, $myfile ) { |
| 28 | if (is_object($myfile) && get_class($myfile)==='CUploadedFile') { |
| 29 | $ext = $model->image->getExtensionName(); |
| 30 | |
| 31 | //generate a filename for the uploaded image based on a random number |
| 32 | // but check that the random number has not already been used |
| 33 | if ($model->filename=='' or is_null($model->filename)) { |
| 34 | $model->filename = uniqid(rand(), true) . \'.\' . $ext; |
| 35 | $model->filename=$filename; |
| 36 | } |
| 37 | |
| 38 | $model->save(); |
| 39 | |
| 40 | $model->image->saveAs($model->getPath()); //model->getPath see below |
| 41 | |
| 42 | $image = Yii::app()->image->load($model->getPath()); |
| 43 | //Crunch the photo to a size set in my System Options Table |
| 44 | //I hold the max size as 800 meaning to fit in an 800px x 800px square |
| 45 | $size=$this->getOption('PhotoLarge'); |
| 46 | $image->resize($size[0], $size[0])->quality(75)->sharpen(20); |
| 47 | $image->save(); |
| 48 | |
| 49 | // Now create a thumb - again the thumb size is held in System Options Table |
| 50 | $size=$this->getOption('PhotoThumb'); |
| 51 | $image->resize($size[0], $size[0])->quality(75)->sharpen(20); |
| 52 | $image->save($model->getThumbnail()); // or $image->save('images/small.jpg'); |
| 53 | return true; |
| 54 | } else return false; |
| 55 | } |
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.
| PHP | | copy code | | ? |
| 01 | |
| 02 | <div class="form" > |
| 03 | <div id="success"> |
| 04 | </div> |
| 05 | |
| 06 | <?php $form=$this->beginWidget('CActiveForm', array( |
| 07 | 'enableAjaxValidation'=>true, |
| 08 | 'id'=>'formPhoto', |
| 09 | 'htmlOptions'=>array('enctype'=>'multipart/form-data', |
| 10 | ), |
| 11 | )); ?> |
| 12 | |
| 13 | Fields with <span class="required">*</span> are required. |
| 14 | <div class="row" > |
| 15 | <?php echo $model->getThumbnail(); ?> |
| 16 | |
| 17 | <?php echo $form->labelEx($model,'filename'); ?> |
| 18 | <?php echo $form->hiddenField($model, 'id'); ?> |
| 19 | <?php echo $form->hiddenField($model, 'property_id'); ?> |
| 20 | <?php echo CHtml::activeFileField($model, 'image'); // see comments below ?> |
| 21 | </div> |
| 22 | <div class="row"> |
| 23 | <?php echo $form->labelEx($model,'caption'); ?> |
| 24 | <?php echo $form->textArea($model,'caption',array('rows'=>6, 'cols'=>50)); ?> |
| 25 | </div> |
| 26 | <div class="row"> |
| 27 | <?php echo $form->labelEx($model,'alt_text'); ?> |
| 28 | <?php echo $form->textField($model,'alt_text',array('rows'=>6, 'cols'=>50)); ?> |
| 29 | </div> |
| 30 | <div class="row"> |
| 31 | <?php echo $form->labelEx($model,'sort_order'); ?> |
| 32 | <?php echo $form->textField($model,'sort_order'); ?> |
| 33 | </div> |
| 34 | <div class="row buttons" id="dvPhotoSubmit"> |
| 35 | <?php echo CHtml::submitButton($model->isNewRecord ? 'Create' : 'Save'); ?> |
| 36 | <?php echo CHtml::button('Cancel',array('onclick'=>"window.parent.$('#cru-dialog').dialog('close');window.parent.$('#cru-frame').attr('src','');")); ?> |
| 37 | </div> |
| 38 | |
| 39 | <?php $this->endWidget(); ?> |
| 40 | </div> |
| 41 | |
| 42 | <!-- form --> |
Model
| PHP | | copy code | | ? |
| 01 | public function getThumbnail(){ |
| 02 | // here i return the image |
| 03 | if (!empty($this->filename) && $this->filename!='') |
| 04 | return CHtml::image($this->getPath(),$this->alt_text,array('width'=>options::model()->getOption('PhotoThumb').'px','max-height'=>options::model()->getOption('PhotoThumb').'px' |
| 05 | )); |
| 06 | } |
| 07 | public function getPath($all=true){ |
| 08 | if (is_null($this->_PhotoPath)) { |
| 09 | // I hold the image path and system directory separator in the config/main.php |
| 10 | // this is because I develop on a windows server and normally deploy on Linux |
| 11 | $this->_PhotoPath=Yii::app()->params['imagePATH']; |
| 12 | $this->_PathSep=Yii::app()->params['pathSep']; |
| 13 | } |
| 14 | $path=$this->_PhotoPath.$this->_PathSep; |
| 15 | if ($all) $path.=$this->filename; |
| 16 | return $path; |
| 17 | } |
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
| PHP | | copy code | | ? |
| 1 | $model->attributes=$_POST['Photos']; |
Blog
Photography
Yii Framework
My Portfolio
Hi, i need help but before that please change these inputs fontcolor, because i cannot see what i type
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
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.
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?
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
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!..
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,
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`)
) ;
Chris
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…
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
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
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…
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
I find the error line 3 in model code : && replace with && a
Thank Chris
Great, thanks for pointing that out. I will update the tutorial.
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.
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;
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.
Hi Sparky
Thanks for the feedback – I'll update the tutorial as you suggested.
many thanks, Chris
Hi, sparky, is it this image extension used in the tutorial?
http://www.yiiframework.com/extension/image/
thanks.
Hi, after i put the function ‘uploadPhoto’ my page show Server Error. May I know why?
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.
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
how are you resizing the image? are you using an extension?
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