Search code examples
phpyii2yii2-advanced-appgii

Testing for POST in Yii 2.0


In my controllers that Gii creates it is common to see the following:

if($model->load(Yii::$app->request->post()) && $model->save()){
//.....do something such as redirect after save....//
}else
{
//.....render the form in initial state.....//
}

This works to test whether a POST is sent from my form && the model that I am specifying has saved the posted information (as I understand it).

I've done this similarly in controllers that I have created myself but in some situations this conditional gets bypassed because one or both of these conditions is failing and the form simply gets rendered in the initial state after I have submitted the form and I can see the POST going over the network.

Can someone explain why this conditional would fail? I believe the problem is with the 'Yii::$app->request->post()' because I have removed the '$model->save()' piece to test and it still bypasses the conditional.

Example code where it fails in my controller:

public function actionFreqopts()
{

    $join = new FreqSubtypeJoin();
    $options = new Frequency();
    $model = new CreateCrystal();
    if ($model->load(Yii::$app->request->post()) && $model->save()) {

        $model->insertFreqopts();
        return $this->redirect(['fieldmap', 'id' => $join->id]);
    } else {
        return $this->render('freqopts', ['join' => $join, 'options' => $options]); 
    }
}

My initial thought was that I'm not specifying the correct "$model" in that I'm trying to save the posted data to FreqSubtypeJoin() in this case and the $model is CreateCrystal(); however, even when I change the model in this conditional it still fails. It would be helpful if someone could briefly explain what the method 'load' is actually doing in layman's terms if possible.


Solution

  • The load() method of Model class is basically populating the model with data from the user, e.g. a post query.

    To do this it firstly loads your array of data in a form that matches how Yii stores your record. It assumes that the data you are trying to load is in the form

    _POST['Model name']['attribute name']

    This is the first thing to check, and, as long as your _POST data is actually getting to the controller, is often where load() fails, especially if you've set your own field names in the form. This is why if you change the model, the model will not load.

    It then check to see what attributes can be massively assigned. This just means whether the attributes can be assigned en-mass, like in the $model->load() way, or whether they have to be set one at a time, like in

    $model->title = "Some title";
    

    To decide whether or not an attribute can be massively assigned, Yii looks at your validation rules and your scenarios. It doesn't validate them yet, but if there is a validation rule present for that attribute, in that scenario, then it assumes it can be massively assigned.

    So, the next things to check is scenarios. If you've not set any, or haven't used them, then there should be no problem here. Yii will use the default scenario which contains all the attributes that you have validation rules for. If you have used scenarios, then Yii will only allow you to load the attributes that you have declared in your scenario.

    The next thing to check is your validation rules. Yii will only allow you to massively assign attributes that have associated rules.

    These last two will not usually cause load() to fail, you will just get an incomplete model, so if your model is not loading then I'd suggest looking at the way the data is being submitted from the form and check the array of _POST data being sent. Make sure it has the form I suggested above.

    I hope this helps!