Wrong URL Parameters in Yii2 form with GET method

This article explains a specific issue with the URL generated when using the GET method with Yii2 forms. Let’s consider, you are using an ActiveForm in yii (both v1.x or 2), with a GET method like below:

// In Yii 2
$form = ActiveForm::begin([
    'id' => 'order-search-form',
    'method' => 'get',
]);
echo $form->field($searchModel, 'id');
echo Html::submitButton('Find', ['class' => 'btn btn-primary']);
ActiveForm::end();

// In Yii 1.x
$form = $this->beginWidget('CActiveForm', [
    'id' => 'order-search-form',
    'method' => 'get',
]);
echo $form->textInput($searchModel, 'id');
echo CHtml::submitButton('Find', ['class' => 'btn btn-primary']);
$this->endWidget();

The problem

On form submission you encounter this situation:

  • Initial uri is order/index.
  • After submitting form with id=111 your URL reads order/index?id=111.
  • After submitting form again your URL reads order/index?id=111&id=111

… and so on. The id parameter in the url as seen, keeps on stacking repeatedly. This is not the correct way you would expect, when submitting a form with GET method.

Explanation

The reason for the above behavior is due to a unique validation needed in Yii’s Html::beginForm method. The query parameters in the action are ignored for GET method so Yii’s Html::beginForm uses hidden inputs for each GET parameter to add them back. These hidden inputs gets stacked over the last URI call with every submission.

Solution

To avoid repeated parameter stacking, ensure you pass the action method while defining your form like below:

// In Yii 2
$form = ActiveForm::begin([
    'method' => 'get',
    'action' => Url::to(['order/index']),
]);

// In Yii 1.x
$form = $this->beginWidget('CActiveForm', [
    'method' => 'get',
    'action' => $this->createUrl('order/index'),
]);

This will automatically use the action URI set above for each form submission rather than relying on the URL from the address bar. Thus the URL parameter repetition and stacking will not happen.