Yii2: #16681 cause error if the $config param not already include 'options' key

Created on 23 Mar 2019  Â·  22Comments  Â·  Source: yiisoft/yii2

16681

    public function widget($class, $config = [])
    {
        foreach ($this->inputOptions as $key => $value) {
            if (!isset($config['options'][$key])) {
                $config['options'][$key] = $value;
            }
        }

must be

    public function widget($class, $config = [])
    {
        foreach ($this->inputOptions as $key => $value) {
             if(!isset($config['options']){
                  $config['options'] = [];
              }
            if (!isset($config['options'][$key])) {
                $config['options'][$key] = $value;
            }
        }
bug

Most helpful comment

That would require any widget to InputWidget, my suggestion would be to check if the class has a 'options' property.

If widget should behave as InputWidget, then it should extend InputWidget. Having options property in widget does not mean that it should be input options. Your PR may break BC by assuming intentions by property name.

All 22 comments

i have this code and i get error on it

`
$form->field($model, "xs")->widget(PhotoInput::className(), [
'form' => $form,
'imgWidth' => 200,
'imgHeight' =>400,
])

`

Thank you for your issue.

Unfortunately code that is not formatted as code blocks is extremely hard to read.
Please check GitHub formatting guide and wrap code accordingly.

Thanks!

_This is an automated comment, triggered by adding the label missing formatting._

Reverted. See https://3v4l.org/D988b

That doesn't solve the problem
PHP: 7.2.10
Yii 2.0.17

<?= $form->field($model, 'test')
    ->widget(Test::class)
    ->label(false); ?>
Unknown Property – yii\base\UnknownPropertyException
Setting unknown property: app\components\test\Test::options

Please post code of Test class.

This foreach probably should be moved under if (is_subclass_of($class, 'yii\widgets\InputWidget')) condition - inputOptions should be populated only for InputWidget instances.

I use to pass in attributes.

public $model;
public $attribute;

If you add $options, everything works. But, this worked and until 2.0.17. I'm not sure this fix should be like this

This foreach probably should be moved under if (is_subclass_of($class, 'yii\widgets\InputWidget')) condition - inputOptions should be populated only for InputWidget instances.

It doesn't work.

@s1lver How it could not work if InputWidget has options property? You will never get UnknownPropertyException exception in this case.

@rob006 the property is, because I added it there to avoid errors. But, why this surplus action?

@s1lver Sorry, I don't get your point. I'm proposing to move this:

https://github.com/yiisoft/yii2/blob/f7fcc0043e1263a281172c8e28c688e2c6e83839/framework/widgets/ActiveField.php#L766-L770

Under this condition:

https://github.com/yiisoft/yii2/blob/f7fcc0043e1263a281172c8e28c688e2c6e83839/framework/widgets/ActiveField.php#L775

You don't need add options property manually, since InputWidget already has it. And if your widget does not extend InputWidget, inputOptions will be ignored like before.

Now, to remedy this situation, I have made the following correction.I think the backwards compatibility was broken.Offer a solution:

if (isset($config['options']) && !isset($config['options'][$key])) {
    $config['options'][$key] = $value;
}

You don't need add options property manually, since InputWidget already has it. And if your widget does not extend InputWidget, inputOptions will be ignored like before.

Yes, I agree with that.

I think we hurried with the correction. Looks like no problem.

@s1lver huh?

@samdark now I can not explain more, but in #17230 is a similar situation. in the process of writing tests, I understood my mistake. not inherited from the desired class. if you look closely at the custom widget, the error is the same for everyone. we are trying to implement inputwidget without implementing all its properties. hence the problem. and this error is absolutely correct. solved by proper legacy or additional implementatio

@rob006 Wrote https://github.com/yiisoft/yii2/issues/17220#issuecomment-476234661:

I'm proposing to move this:

yii2/framework/widgets/ActiveField.php

Lines 766 to 770 in f7fcc00

     foreach ($this->inputOptions as $key => $value) { 
         if (!isset($config['options'][$key])) { 
             $config['options'][$key] = $value; 
         } 
     }

Under this condition:

yii2/framework/widgets/ActiveField.php

Line 775 in f7fcc00

     if (is_subclass_of($class, 'yii\widgets\InputWidget')) {

You don't need add options property manually, since InputWidget already has it. And if your widget does not extend InputWidget, inputOptions will be ignored like before.

That would require any widget to InputWidget, my suggestion would be to check if the class has a 'options' property. Please see #17231

@webinjaz Could you please have a look at #17230 and check if the workaround mentioned there solves your problem or if would still remain, which would mean you're having a different problem.

That would require any widget to InputWidget, my suggestion would be to check if the class has a 'options' property.

If widget should behave as InputWidget, then it should extend InputWidget. Having options property in widget does not mean that it should be input options. Your PR may break BC by assuming intentions by property name.

Having options property in widget does not mean that it should be input options. Your PR may break BC by assuming intentions by property name.

I agree. But that also works the other way around:

If widget should behave as InputWidget, then it should extend InputWidget.

Aren't you then use the class InputWidget as an interface? If so, I think it should have it's own InputWidgetInterface or ActiveFieldWidgetInterface.

If so, I think it should have it's own InputWidgetInterface

Technically - yes, it should be an interface. But interfaces cannot contain properties, so changing this will be too invasive for Yii2. It is rather a topic for Yii3.

Expected behaviour

class TestCustomInputWidget extends InputWidget
{
    public $model;
    public $attribute;
}

or

class TestCustomInputWidget extends InputWidget
{
    public function run()
    {
        $this->model;
    }
}

Error-causing implementation

class TesCustomWidget extends Widget 
{
    public $model;
    public $attribute;
}

image

Here I want to implement my widget, the error is logical, as ActiveField expects $options. But this is not implemented in the widget.

Therefore, I believe that this is more of a logical error in creating a widget than in ActiveField.

Was this page helpful?
0 / 5 - 0 ratings