Ruslan Polutsygan
Ruslan Polutsygan

Reputation: 4461

Yii form builder

I've been working on Yii-based application. And I've faced with weird thing...

What I'm trying to do is to add input(type=file) into form. Form is created via form builder(CForm class). But input is not going to appear.

My code. Controller/action:

$model=MyModel::model()->findByPk(700);
$model->scenario='my-scenario';
$form=new CForm('path.to.forms.my-form', $model);

$this->render('view', array('form'=>$form));

View:

echo $form

Form config:

return array(
    'attributes' => array(
        'enctype' => 'multipart/form-data',
    ),
    'elements' => array(
        'name' => array(
            'type' => 'text',
        ),
        'image' => array(
            'type' => 'file',
        ),
    ),
    'buttons' => array(
        'save' => array(
            'type' => 'submit',
            'label' => 'Save',
        ),
    ),
);

Model:

//.....
public $image;
// ....
public function rules()
{
    return array(
    //...
        array('image', 'file', 'types'=>'png', 'on'=>'my-scenario'),

    );
}

With code above I expected to see two fields - text and file. But only text one appears.

If I change file validator to, say, required - it works, but I need file validator.

I'm using Yii version 1.1.13.

The most intresting that code above works as expected with earlier Yii(1.1.9). Is this a known bug in new version? If yes - is there a solution? or do I have to rollback to previous version?

Thanks in advance.

UPDATE:

If you add a second validator (one for file and one for required) does it work?

No, it doesn't. I believe I found why. See bellow.

It seems to be caused by this line in CForm..

Yes, correct. Yesterday, armed with debugger I went deeper:)

CFormElement::getVisible() eventually calls CModel::isAttributeSafe() and CModel::getSafeAttributeNames().

CForm::getSafeAttributeNames() gets all model validators and leaves only safe ones. As we can see CFileValidator is not safe.

So, it doesn't matter how many safe validators(required or any other) have attribute assigned. CForm::getSafeAttributeNames() removes it from whitelist if there is at least one unsafe(file). File validator is unsafe since 1.1.12 version. That is why it worked perfectly for me in 1.1.9 :)

Hence the problem is in CFileValidator(or at least connected with it) and not in CForm.

The only one solution I can see so far is creating own validator extended from CFileValidator marked safe and using it instead of built in. But I can't even imagine what problems it may cause(I believe Yii developers had a good reason for making it unsafe).

I hope this will be helpful for somebody.

UPDATE 2

array('image', 'file', 'safe'=>true, 'types'=>'png', 'on'=>'my-scenario')

this validation rule(explicit safe=true) also works.

Upvotes: 2

Views: 1960

Answers (2)

Ruslan Polutsygan
Ruslan Polutsygan

Reputation: 4461

Issue has been posted on github

https://github.com/yiisoft/yii/issues/2089

Upvotes: 1

acorncom
acorncom

Reputation: 5955

If you add a second validator (one for file and one for required) does it work? I ran into this recently myself.

It seems to be caused by this line in CForm:

if($element->getVisible())
{
    ...
}

The getVisible checks the active validators for this current model scenario and leaves out any inputs that aren't used in the current validator rules. I've ended up commenting things out in our custom CForm model for our system, but if let me know if you find something that works better for you.

Upvotes: 1

Related Questions