keneso
keneso

Reputation: 311

Yii2 adding an extra field to the form to add to database

On an existing project there is a table with 3 fields (ID, name, label)

`id` int(11) NOT NULL,
`name` varchar(32) DEFAULT NULL,
`label` varchar(1) DEFAULT 'A'

Currently, on the products/create and products/update pages there is a form with only one field for 'name'. I need to add another field 'label'.

Before the update, models/Products.php has this code:

class Products extends \yii\db\ActiveRecord
{
    /**
     * {@inheritdoc}
     */
    public static function tableName()
    {
        return 'products';
    }
    
    /**
     * {@inheritdoc}
     */
    public function rules()
    {
        return [
            [['name'], 'string', 'max' => 32],
            [['name'], 'unique'],
        ];
    }
    
    /**
     * {@inheritdoc}
     */
    public function attributeLabels()
    {
        return [
            'id' => Yii::t('app', 'ID'),
            'name' => Yii::t('app', 'Name'),
        ];
    }
}

I add the following to the above file, but no new input field is added to the form on the page:

public function attributeLabels()
{
    return [
        'id' => Yii::t('app', 'ID'),
        'name' => Yii::t('app', 'Name'),
        'label' => Yii::t('app', 'Prefix'),
    ];
}

I also tried adding to the rules like this, but no joy

public function rules()
{
    return [
        [['name', 'label'], 'string', 'max' => 32],
        [['name', 'label'], 'unique'],
    ];
}

Upvotes: 1

Views: 639

Answers (1)

Raul Sauco
Raul Sauco

Reputation: 2705

You need to add the field to the HTML form.

If you open the file products/views/_form you will see the following line:

<?= $form->field($model, 'name')->textInput(['maxlength' => true]) ?>

You need to add a new field for the label attribute, Yii will use the rules and label from the model to generate the field for the attribute, add this new line:

<?= $form->field($model, 'name')->textInput(['maxlength' => true]) ?>
<?= $form->field($model, 'label')->textInput(['maxlength' => true]) ?>

Given your table fields:

`id` int(11) NOT NULL,
`name` varchar(32) DEFAULT NULL,
`label` varchar(1) DEFAULT 'A'

You probably want to update the rules to this, not to the ones you show:

public function rules()
{
    return [
        [['name',], 'string', 'max' => 32],
        [['label',], 'string', 'max' => 1],
        [['name',], 'unique'],
        // Do not make label unique.
        // [['name', 'label'], 'unique'],
    ];
}

label has a max length of 1 on the database, if you give it a max length of 32 on the ActiveRecord, it will let the user enter values longer than 1 byte, it will try to insert that value into the database, and an exception will be thrown.

If you make label unique, since it has a max length of 1, that will limit the maximum number of records that the table can hold to 256. You won't be able to reuse any of the labels, for example, there cannot be two records labeled "A", since that is the default value for the column, if you already have a record labeled "A" and you try to insert a new record leaving the label field empty, it will also result in an exception.

You may want to consider adding a required rule if you keep unique:

[['label',], 'required'],

Upvotes: 1

Related Questions