sємsєм sємsєм - 4 years ago 916
SQL Question

Yii2 and float field with default value NULL

In the official documentation example "Country" database. I decided to add new field (Property) for the country, namely,

area
. I added a field named to the MySQL database's table named
country
with the name
area
with the following structure:

`area` float DEFAULT NULL


The new field's values in the database takes the default value
0
and in the view it displayed as
0.00
like the following screen shot shows:

enter image description here

In the update form, I added an input field for
area
like the following:

// In views/country/_form.php, I added the following line to the form:
<?= $form->field($model, 'area')->textInput() ?>



//In models/Country.php, I did not set any validation rules for area field.
public function attributeLabels()
{
return [
'code' => 'Code',
'name' => 'Name',
'population' => 'Population',
'area' => 'Area in KM<sup>2</sup>'
];
}


Now all fields in update view, are updated successfully, except the new field
area
. It, simply, does not updated at all without any error messages. Why?

Also, as the screen shot shows, in the view
area
label is printed out correctly, however, in the update view it shows as its HTML entity i.e
Area in KM<sup>2</sup>
. Why?

In another aspect, I did not like the presentation of area for non defined area country by 0.00, so I decidd to make it to be
N/A
so I have made the following callback method in models/Country.php:

public function afterFind()
{
if ($this->area == NULL){
$this->area = 'N/A';
}
return true;
}


However, the above solution generates error in the action view:


'N/A' is not a numeric value.


So, I replaced
N/A
with
NULL
and the view action works fine and assigned non defined area countries with
(not set)
in the view instead of
0.00
. The last question here, is there any way to make the view printout
N\A
for non defined area countries? The action view uses
DetailView::widget

Answer Source

Now all fields in update view, are updated successfully, except the new field area. It, simply, does not updated at all without any error messages. Why?

Because it's not safe attribute. You said that it's not presented in the rules. If you don't want validate it, but want to be able to massively assign it, you should explicitly specify it in the validation rules like so:

['area', 'safe'],

Read more about model safe attributes in official documentation.

Also, as the screen shot shows, in the view area label is printed out correctly, however, in the update view it shows as its HTML entity i.e Area in KM<sup>2</sup>. Why?

That's how attribute label renders in DetailView:

https://github.com/yiisoft/yii2/blob/master/framework/widgets/DetailView.php#L206

And in Html::activeLabel() which is used by ActiveForm's field():

https://github.com/yiisoft/yii2/blob/master/framework/helpers/BaseHtml.php#L1048

If it's not specified explicitly and automatically taken from attributeLabels(), encoding applies regargless of the options.

As as a workaround in ActiveForm I recommend passing it like this:

<?= $form->field($model, 'area')->label('Area in KM<sup>2</sup>') ?>

I think it's not a big deal to copy such content, because it's not code logic and rarely changed. And even if it will change, it's very easy to replace it with global search in your editor. If you highly against that, maybe it's better to declare it additionally in your model.

If you want, you can create issue on Github about that. Maybe I missed something but I didn't find a way to disable encoding for labels in ActiveForm.

And another workaround is to simply replace html by text representation, something like square km. It's a bit longer, but does not have this problems with encoding.

The last question here, is there any way to make the view printout N\A for non defined area countries?

I think what you doing in afterFind() is not good because you replace the actual model value with display value. It can be used somewhere else, for example in update process and lead to some bugs.

You can do it at least with two options in your view.

1) If the null values are presented only in area, or you want to display N\A for other attributes null values too, you can simply replace default null representation like so:

use Yii;

...

Yii::$app->formatter->nullDisplay = 'N\A';

You should place this code before rendering DetailView Read more in official documentation.

2) Otherwise just extend defition of attribute area in DetailView attributes section:

[
    'attribute' => 'area',
    'value' => $model->area === null ? 'N\A' : $model->area,
],
Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download