file-uploadyiiyii-cformmodel

Yii file CFormInputElement won't display unless explicitly marked "safe"


I'm trying to use Form Builder to build a simple file upload prompt. I want to specify the rule for the file to be similar to

array('formFile', 'file', 'allowEmpty' => false, 'types' => 'html'),

but something is wrong. The file upload element only appears if I explicitly mark the element as 'safe' (and remove the 'file' rule). What am I missing?

models/UploadForm.php

class UploadForm extends CFormModel
{
    public $year;
    public $formFile;

    public function rules ()
    {
        return array(
            array('year',    'required'),
            array('year',    'date', 'format'=>'yyyy'),
//            array('formFile', 'safe'),
            array('formFile', 'file', 'allowEmpty' => false, 'types' => 'html'),
        );
    }

    static public function getYearOptions () {...}
}

views/extranet/uploadForm.php

return array(
    'title' => 'Select year',
    'method' => 'post',
    'enctype' => 'multipart/form-data',

    'elements' => array(
        'year' => array(
            'type'  => 'dropdownlist',
            'items' => UploadForm::getYearOptions(),
        ),
        'formFile' => array(
            'type'  => 'file',
            'label' => 'form source file',
        ),
    ),

    'buttons' => array(
        'upload' => array(
            'type'  => 'submit',
            'label' => 'upload',
        ),
    ),
);

controllers/ExtranetController.php

class ExtranetController extends CController
{
    public function actionIndex ()
    {
        $form = new CForm('application.views.extranet.uploadForm', new UploadForm());
        if ($form->submitted('upload') && $form->validate()) {...}
        $this->render('index', array('form' => $form));
    }
}

Solution

  • The reason for this is very simple.

    The form builder only renders input elements which are considered safe (I.E. have a validation rule). What you have done is perfectly fine, except CFileValidator isn't "safe" by default, whereas other validators are safe.

    The quickest way to solve this is the following:

    // In your model::rules() function
    return array(
        array('formFile', 'file', 'allowEmpty' => false, 'types' => 'html', 'safe' => true),
    );
    

    Refer to these two links for more information: the CFileValidator#safe documentation, and the Github issue for a problem very similar to yours.