Using Cuploadedfile In My Model

Hi,

I’ve got a model who handles all the stuff for images. It saves a record to the DB. It stores the uploaded image and it creates thumbnails.

I use this on a lot of places in controllers, so the only lines I need for that are:




$images = CUploadedFile::getInstancesByName('images');

					

if(isset($images) && count($images) != 0) 

{

  foreach($images as $image)

  {	

    $newBaseImage = new BaseImage();

    $newBaseImage->setFile($image);

    $newBaseImage->save();

  }

}				



In my model BaseImage i’ve got a setter setFile():




// Set file.

public function setFile($file)

{

  if($file instanceof CUploadedFile)

    $this->file = $file;

  else

    throw new Exception("file has to be an instance of CUploadedFile", 1);	

}



Works great. But now I have a situation that I don’t want to store an uploaded image, but a file created with GDlib imagejpeg() function.

But I can’t create a file and then load it into a CUploadedFile object right? That would be bad coding I guess.

What options do I have? I can’t find a class like CUploadedFile in Yii to use for this.

No ideas I guess. Maybe it’s not possible what I want. I’m working with a workaround now. So it’s possible to set an uploaded image and it’s possible to work without it. Then I store the image manually and after that I call the create thumbnails method again. It’s not pretty, but I don’t know how else to do.

If someone has a hint for me, please let me know.

You can rewrite BaseImage for processing other parameters not only CUploadedFile and resize images outside the model.





$newBaseImage = new BaseImage();


$tmp = tempnam(sys_get_temp_dir(), 'xxx_');

$image->saveAs($tmp);

 

BaseImage::resizeFile($tmp); //resize $tmp file via GD or Imagick


$newBaseImage->setFile($tmp);

$newBaseImage->save();


public function setFile($file)

{

  $this->file = $file;

  if ($file instanceof CUploadedFile) {

     $this->mimetype = $file->getType();

     $this->size = $file->getSize();

  } else {

     $this->mimetype = CFileHelper::getMimeType($file);

     $this->size = filesize($file);

  }

}


public function afterSave() { //or special method called manually

    if ($this->file instanceof CUploadedFile) {

       $this->file->saveAs($this->getFileName());

    } else {

       rename($this->file, $this->getFileName());

    }

}



Or you can resize CUploadedFile inside the model.





$newBaseImage = new BaseImage();

$newBaseImage->setFile($image);

$newBaseImage->save();


public function afterSave() { //or special method called manually

    $this->file->saveAs($this->getFileName());

    BaseImage::resizeFile($this->getFileName()); //resize $tmp file via GD or Imagick

}



Other approach:

You can always save original uploaded image and resize it on request only.

Then you will generate thumbails on fly and cache it (manually or via nginc)

Hi Sleptor,

Thanks a lot for taking the effort to explain this. I think this is the best solution to modify my models setFile() method for accepting a CUploadedFile object or just an array with (name,location,extension, etc.). And also I’ve added a flag


private generateThumbnails = true;

which can be set to false in the case of a non CUploadedFile. Also the storeImage() method I’m not using the saveAs() option of the CUploadedFile anymore, but just the moveuploadedfile() function.




    // After save.		

    public function afterSave()

    {

    	// Store image if set.	

    	if(isset($this->file))

    	  $this->storeImage();

			

	// Generate thumbnails.	

	if($this->generateThumbnails == true)

	  $this->generateThumbnails();			


	return true;

    }



Still it feels a little messy, but I have that a lot when I create my classes. Maybe I want them to be to perfect. Or I’ve got to learn a lot more about OOP to make it more slick and clean.