Thursday, February 24, 2011

Re: Model data appears to unset after save, is this correct?

Thanks Cricket,

I realise a lot of the stuff i'm doing in the model would be better served in a component - maybe one day if i revisit it i'll break it out properly into a component... for the time being it "works", and its not "wrong" ... maybe just not as "right" as it could be :P




On Fri, Feb 25, 2011 at 5:43 AM, cricket <zijn.digital@gmail.com> wrote:
On Thu, Feb 24, 2011 at 3:43 AM, Greg Skerman <gskerman@gmail.com> wrote:
> Hi,
>
> I've been working on a very simple app to upload and resize some images, and
> name the file in accordance with some information that has been provided in
> a form.
>
> To do this, my model has a public method "createFilename", which relies on
> $this->data to build the filename in accordance with the provided business
> rules.
>
> It was all working fine, until I connected the model to a database table and
> started also saving the meta-data.... now it appears $this->data is being
> unset for subsequent calls to the method.
>
> The method is simple enough:
>
> public function createFilename() {
>
>         CakeLog::write('debug', 'photo name is '.
> $this->data['Photo']['name']);
>
>         $name = $this->data['Photo']['name'];
>
>         $level = $this->data['Photo']['level'];
>
>         $category = $this->data['Photo']['category'];
>
>         $month = strtoupper($this->data['Photo']['month']);
>
>
>         return $level . $category . $month . $name . '.jpg';
>
> }
>
>
> According to the information that I log, in the 4 times this method is
> called during the processing of the image, the first time
> $this->data['Photo']['name']  contains data, and then each subsequent call
> is empty.
>
> The first time the method is called is at validation to prevent duplicate
> files with the same metadata being created, and this seems to be working
> fine, but then the following times (which are used for naming the file after
> it has been manipulated, moving the file out of the TMP directory into the
> uploaded images directory, and including the filename in an email
> attachment, $this->data appears to be empty.

I realise, from your other post, that you're not doing calling that
method repeatedly anymore. It's really inefficient to do that.

The way I've approached this is to use a FileHandlerComponent and
ImageHandlerComponent. Any controller that deals with an upload calls
__handleUpload() after saving the record. The first component deals
with moving the file to the correct location and the second with
resizing. I split them into separate components because I deal with a
lot of non-image uploads.

Example from FilesController:

private function __handleImageUpload()
{
       $this->FileHandler->setModelName('Link');
       $this->FileHandler->setBase(WWW_ROOT);
       $this->FileHandler->setSubDirectory('files/links');

       if ($this->FileHandler->upload('upload', false))
       {
               $upload_data = $this->FileHandler->getUploadData();

               /* create a reasonably-sized image
                */
               if (!empty($upload_data))
               {
                       /* resize if necessary
                        */
                       $img_data = $this->ImageHandler->apply(
                               array_merge($this->Link->image_settings, array('basename' =>
$upload_data['basename'])),
                               $this->FileHandler->getBase().$upload_data['directory'].DS.$upload_data['basename'],
                               $upload_data['directory'].DS.$upload_data[0]['basename']
                       );

                       /* Save image details
                        */
                       if (is_array($img_data) && !empty($img_data))
                       {
                               $data = array(
                                       'Link' => array(
                                               'id' => $this->Link->id,
                                               'directory' => $upload_data[0]['directory'],
                                               'basename' => $img_data['basename'],
                                               'extension' => $img_data['extension'],
                                               'type' => $img_data['type'],
                                               'size' => $img_data['size'],
                                               'width' => $img_data['width'],
                                               'height' => $img_data['height']
                                       )
                               );

                               /* see if there's already an image
                                */
                               $old_image = $this->Link->find(
                                       'first',
                                       array(
                                               'conditions' => array('id' => $this->Link->id),
                                               'recursive' => -1
                                       )
                               );

                               if ($this->Link->save($data, false))
                               {
                                       if (isset($old_image['Link']['basename']))
                                       {
                                               unlink(WWW_ROOT.$old_image['Link']['directory'].DS.$old_image['Link']['basename']);
                                       }
                               }


The model var $image_settings contains things like the maximum width &
height, etc.

Dealing with existing images (whether to overwrite, how to re-name)
could also be done within the component, as long as the model save is
also done there (because you don't want to unlink a file if the new
record didn't save).


> Does the act of saving a record to the database automatically unset the
> $this->data variable or is there something else going on here?

Only for the model. The controller's data is still available.

--
Our newest site for the community: CakePHP Video Tutorials http://tv.cakephp.org
Check out the new CakePHP Questions site http://ask.cakephp.org and help others with their CakePHP related questions.


To unsubscribe from this group, send email to
cake-php+unsubscribe@googlegroups.com For more options, visit this group at http://groups.google.com/group/cake-php

--
Our newest site for the community: CakePHP Video Tutorials http://tv.cakephp.org
Check out the new CakePHP Questions site http://ask.cakephp.org and help others with their CakePHP related questions.
 
 
To unsubscribe from this group, send email to
cake-php+unsubscribe@googlegroups.com For more options, visit this group at http://groups.google.com/group/cake-php

No comments: