[SOLVED] Upload function does not work

I am building a file upload function basically according to the cookbook page.

protected/controllers/ItemController.php:

  public function actionUpload()


  {


    $model=new Item;


    print_r($_POST); // for debugging purpose


    if(isset($_POST['Item']))


      {


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


        $model->image=CUploadedFile::getInstance($model,'image');


        if($model->save())


          {


            $model->image->saveAs('/tmp/files');


            $this->redirect('success');


          }


      }


    $this->render('upload', array('model'=>$model));


  }


protected/views/item/upload.php:

Input your file name: <br>


<?php echo CHtml::form('','post',array('enctype'=>'multipart/form-data')); ?>


<?php echo CHtml::activeFileField($model, 'image'); ?>


<br>


<?php echo CHtml::submitButton('Upload', array('name'=>'submitPost')); ?>


</form>


When I selected a file and clicked a submit button, no file was uploaded. And I inserted print_r as shown above, it displayed 'Array ( [submitPost] => Upload )' and there is no attributes there. Where am I wrong?

Here is the generated HTML and the default action is 'actionUpload()'.

<form enctype="multipart/form-data" action="/demos/blog-uploader/index.php/item" method="post">


<input name="Item[image]" id="Item_image" type="file" />


<br>


<input name="submitPost" type="submit" value="Upload" /></form>


Your code looks fine to me. You should print_r($_FILES) though.

Thanks Qiang,

Quote

Array ( [Item] => Array ( [name] => Array ( [image] => 1559849383_96bcc8c09a.jpg ) [type] => Array ( [image] => image/jpeg ) [tmp_name] => Array ( [image] => /tmp/phpFSRWqi ) [error] => Array ( [image] => 0 ) [size] => Array ( [image] => 80981 ) ) )

1559849383_96bcc8c09a.jpg is the file that I have selected.

What does this line give to you?

$model->image=CUploadedFile::getInstance($model,'image');

I replaced 'print_r($_POST);' statement as what you said.

    $model->image=CUploadedFile::getInstance($model,'image');


    print_r($model->image);


And it displays:

Quote

CUploadedFile Object ( [_name:private] => 1559849383_96bcc8c09a.jpg [_tempName:private] => /tmp/phpKlg3Zk [_type:private] => image/jpeg [_size:private] => 80981 [_error:private] => 0 [_e:private] => [_m:private] => )

BTW, the model class Item is defined as follows, because there was an error message saying 'The table "Item" for active record class "Item" cannot be found in the database.', when I had defined the class Item as an extention of CActiveRecord.

<?php


class Item extends CFormModel


{


  public $image;


 


  public function rules()


  {


    return array(


                 array('image', 'file', 'types'=>'jpg, gif, png'),


                 );


  }


}


I think the system should take care of the attribute processing…

So you did get the file. What is the issue here?

Thank you for your reply Qiang,

I was not get the model inside the "if(isset($_POST['Item']))" block. When I moved following two lines out, then the result is as my previous post.

    $model->image=CUploadedFile::getInstance($model,'image');


    print_r($model->image);


In short, the variable of $_POST['Item'] is not set, as my first post says, and I was not able to do the process inside the if block.

I see. Could you please create a ticket for this? not really an issue, but I think we may find a good way to avoid this situation.

Thank you for the investigation, Qiang. Issue207.

I have noticed that there was NO method such as save() in the CFormModel class.

Then I should change models/Item from CFormModel to CActiveRecord. Do I need to define it as a instance of CActiveRecord class even though file uploading is not related to DB at all?

What does CFormModel.save() mean? You can easily define one yourself if save() makes sense in your case. If the uploaded file has nothing to do with DB and is the only field, I see no reason why you have to use CActiveRecord.

The main reason for your issue here is because there is no other model field and thus $_POST['Item'] is not set (since file field is using $_FILES, not $_POST).

Quote

What does CFormModel.save() mean?

I don’t know. I am chasing the cookbook page. In this post, it says;

Quote

First declare an attribute to store the file name in the model class (either a form model or an active record model).

Then I defined my class as follows as I already mentioned. I modified this code from CActiveRecord to CFormModel because there was an error when I had defined it as CActiveRecord as I already mentioned.

<?php


class Item extends CFormModel


//class Item extends CActiveRecord


{


  public $image;


 


  public function rules()


  {


    return array(


                 array('image', 'file', 'types'=>'jpg, gif, png'),


                 );


  }


}

But to consult the class reference, I have found there is no save() method in CFormModel class, though the cookbook says as follows;

Quote

Then, in the controller class define an action method to render the form and collect user-submitted data.

class ItemController extends CController

{

    public function actionCreate()

    {

        $model=new Item;

        if(isset($_POST['Item']))

        {

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

            $model->image=CUploadedFile::getInstance($model,'image');

            if($model->save())

Quote

You can easily define one yourself if save() makes sense in your case. If the uploaded file has nothing to do with DB and is the only field, I see no reason why you have to use CActiveRecord.

Then what should I do? Sould I forget about the coockbook code?

Quote

The main reason for your issue here is because there is no other model field and thus $_POST['Item'] is not set (since file field is using $_FILES, not $_POST).

There may be an attribute $image in Item class. Again, should I forget about the cookbook code and build my own using $_FILES? ???

The cookbook page assumes you are using CActiveRecord and thus you can do saving (since it means saving the data to database). If you use CFormModel, you need to define yourself what save() means because CFormModel is not tied with database.

A workaround to your problem is to check isset($_POST['submitButtonName']).

Thank you for your suggestion Qiang. I was able to make it work. The code follows.



  public function actionUpload()


  {


    $model=new Item;





    if(isset($_FILES['Item'])) {


      $model->image=CUploadedFile::getInstance($model,'image');


     


      if($model->validate())


        {


          $model->image->saveAs('/tmp/files/'.$model->image->name);


          $this->redirect('item/success');


        }


    }


    $this->render('upload', array('model'=>$model));


  }