scenariusz pobiera się poprawnie ale nie działa walidacja

Cześć, robię cruda w yii2. Pobieram dane użytkownika do dwóch modeli. Jeden jest wymagany drugi nie. Jeśli użytkownik kliknie checkboxa (firma) to pokazują mu się dodatkowe dane które musi uzupełnić. To pobieranie musi działać na scenariuszach- jeśli checbox=1 to dane pola z formularza muszą przejść walidację w rulsach required jeśli checkbox jest wylaczony to dodatkowy formularz nie wyswietla się i jego atrubuty sa ustawione na safe. To jest moja akcja z kontrolera:


public function actionCreate() {

        $model = new UrUserForm();

        $userDate = new UserDataForm();

        $model->scenario = 'create';

        

        if (($userDate->load(Yii::$app->request->post()) && $userDate->validate() && $model->load(Yii::$app->request->post()) && $model->validate()) || $model->load(Yii::$app->request->post()) && $model->validate()) {

           

            if ($userDate->IsCompany()) {

                $userDate->scenario = 'setFirm';

            } else {

                $userDate->scenario = 'notFirm';

                $userDate->clearData();

            }

            var_dump($userDate->scenario);

            exit();

            $userDate->saveOptionalData();

            $model->RoyalUserData=$userDate->data['Id'];

            $model->saveUser();

            

            Yii::$app->session->setFlash('success', 'Użytkownik został dodany');

            return $this->redirect(['index']);

        } else {

            return $this->render('create', [

                        'model' => $model,

                        'userDate' => $userDate

            ]);

        }

    }

A tutaj model chyba wystaczy ten jeden, gdzie próbuję utworzyć scenariusze:


<?php

namespace backend\modules\users\models;


use common\models\UserData;

use frontend\modules\settings\models\Profile;


use yii\base\Model;

use Yii;


class UserDataForm extends Model

{

    public $Address;

    public $NIP;

    public $CompanyName;

    public $Website;

    public $Phone;

    public $IsCompany;

    public $IsPhoneConfirmed;

    public $CreatedAt;

    public $UpdateAt;

    public $Rel_State;

    public $Rel_Currency;

    public $IsDeleted;

    public $data;

    

    public function rules()

    {

        return [

            [['Address', 'Phone', 'Rel_State', 'Rel_Currency','IsCompany'], 'safe', 'on' => 'notFirm'],

            [['Address', 'Phone', 'Rel_State', 'Rel_Currency','IsCompany'], 'required', 'on' => 'setFirm'],

            [['NIP','IsCompany', 'Phone', 'IsPhoneConfirmed', 'CreatedAt', 'UpdateAt', 'Rel_State', 'Rel_Currency', 'IsDeleted'], 'integer'],

            [['Address', 'CompanyName', 'Website'], 'string', 'max' => 45],

            [['Phone'], 'common\components\validators\PhoneValidator'], 

            [['NIP'], 'common\components\validators\NipValidator'],

            ['IsCompany', 'safe']

        ];

    }

    

    public function scenarios()

    {

        $scenarios = parent::scenarios();

        $scenarios['setFirm'] = ['Address', 'Phone', 'Rel_State', 'Rel_Currency','IsCompany'];

        $scenarios['notFirm'] = ['Address', 'Phone', 'Rel_State', 'Rel_Currency','IsCompany'];

        return $scenarios;

    }

    

     public function saveOptionalData() {


        $model = new UserData();

        $model->Address=$this->Address;

        $model->Phone=$this->Phone;

        $model->Rel_State=$this->Rel_State;

        $model->Rel_Currency= $this->Rel_Currency;

        $model->NIP=$this->NIP;

        $model->IsCompany = $this->IsCompany;

        $model->IsPhoneConfirmed = $this->IsPhoneConfirmed;

        $model->CompanyName = $this->CompanyName;

        $model->Website = $this->Website;

        $this->data=$model;

        if ($model->validate() && $model->save()) {

            return $model;

        }

        return false;

    }

           

    public function clearData() {

        $this->Address = NULL;

        $this->Phone = NULL;

        $this->Rel_State = NULL;

        $this->Rel_Currency = NULL;

        $this->NIP = NULL;

        $this->IsCompany = NULL;

        $this->IsPhoneConfirmed = NULL;

        $this->CompanyName = NULL;

        $this->Website = NULL;

    }


    public function IsCompany() {

        

        if ($this->IsCompany == 1) {

            return true;

        }

        return false;

    }

    }



Pomoże ktoś, pewnie mam coś źle w funkcji scenario, czytałem dokumentacje ale to mi nie pomaga. W akcji create stworzyłem vardumpa który wskazuje na to, że tam jest wszystko okej bo gdy odznaczę checkoboxa to vardump wypluwa: string(7) "notFirm" a jak go zaznacze to: string(7) "setFirm". Nie wiem gdzie może tkwić błąd ale za każdym razem valdiacja w tym drugim formularzu ustawia się na safe, czyli dane z rulsów(addres, phone) przechodzą a powinno być tak, że jak zaznacze checkboxa i nie wypełnię tych pól to powinno walić walidację. Ktoś potrafi mi pomóc?

Scenariusz musi być ustawiony przed walidacją. U siebie najpierw ładujesz dane do modelu, walidujesz (wszystko to wykorzystuje reguły domyślnego scenariusza), a dopiero później zmieniasz scenariusz. Same warunki w ifie też wyglądają podejrzanie.

warunki w ifie powineinem przerobić na dwie części? Jeśli użytkownik wypełnił pierwszą część formularza i nie zaznaczył checkboxa to powinien pójść w scenariusz notFirm.

scenariusz dałem nad rulsami i dalej to samo

Scenariusz musi być ustawiony przed walidacją, a nawet lepiej byłoby go ustawić przed załadowaniem danych z POSTa do modelu. Ale najlepiej byłoby skorzystać z walidacji warunkowej: http://www.yiiframework.com/doc-2.0/guide-input-validation.html#conditional-validation

A if może podejrzanie wygląda ale jeśli chodzi o sam scenariusz to przechodzi bo tak jak napisałem, var_dump wyświetla poprawnie scenariusz więc chyba nie jest tak źle.

przed validacją czyli przed rulsami w modelu?

If jest bez sensu bo masz zduplikowany warunek &#036;model-&gt;load(Yii::&#036;app-&gt;request-&gt;post()) &amp;&amp; &#036;model-&gt;validate().

Nie wiem o jakich rulsach mówisz. Chodzi mi o &#036;model-&gt;validate() - w tym momencie uruchamiasz walidację i robisz to przed ustawieniem scenariusza.

Hmm chodzi Ci w w kontrolerze. Hmm to nie mam pomysłu jak to ogarnąć

Hmm nawet gdy na testa ustawiłem walidację po scenariuszu do dalej mi nie wchodzi:


public function actionCreate() {

        $model = new UrUserForm();

        $userDate = new UserDataForm();

        $model->scenario = 'create';

        

        if (($userDate->load(Yii::$app->request->post()) && $model->load(Yii::$app->request->post())) || $model->load(Yii::$app->request->post())) {

           

            if ($userDate->IsCompany()) {

                $userDate->scenario = 'setFirm';

            } else {

                $userDate->scenario = 'notFirm';

                $userDate->clearData();

            }

            $model->validate();

            $userDate->validate();

            $userDate->saveOptionalData();

            $model->RoyalUserData=$userDate->data['Id'];

            $model->saveUser();

            

            Yii::$app->session->setFlash('success', 'Użytkownik został dodany');

            return $this->redirect(['index']);

        } else {

            return $this->render('create', [

                        'model' => $model,

                        'userDate' => $userDate

            ]);

        }

    }

Skorzystaj z walidacji warunkowej, tak jak ci wcześniej napisałem. Zamiast


'on' => 'setFirm'

dajesz


'when' => function($model) {

    return $model->IsCompany()';

}

i w ogóle wywalasz warunki ze scenariuszami z kontrolera. Prawdopodobnie przed taką regułą musi być reguła dotycząca IsCompany.

Reguły walidacji są wykorzystywane też przy &#036;model-&gt;load() - jeśli dla danego atrybutu nie ma żadnej reguły, to nie będzie on ustawiony podczas load(). Dlatego jeśli bazujesz na scenariuszach powinieneś go ustawić przed loadi validate().

A w tym ifie próbuję sprawdzić


 if (($userDate->load(Yii::$app->request->post()) && $userDate->validate() && $model->load(Yii::$app->request->post()) && $model->validate()) || $model->load(Yii::$app->request->post()) && $model->validate()) 

czyli jeśli wypełnił dane z pierwszego i dodatkowego formularza to idź dalej, || lub pobrał dane tylko z pierwszego to też idź dalej nie wiem jak to można inaczej zaifować. Bo może wypełnić tylko jeden ten pierwszy podstawowy ale może uzupełnić też drugi formularz więc dałem "||"

W twoim warunku jeśli &#036;model-&gt;validate() zwraca false, to i tak próbujesz jeszcze raz załadować dane do modelu i ponownie sprawdzasz &#036;model-&gt;validate() choć już raz to zrobiłeś. Prawdopodobnie identyczny wynik uzyskałbyś warunkiem:


$model->load(Yii::$app->request->post()) && $model->validate() && $userDate->load(Yii::$app->request->post()) && $userDate->validate()

Nie za bardzo rozumiem dopiero się uczę Yii2 i zrobiłem coś takiego:


 public function actionCreate() {

        $model = new UrUserForm();

        $userDate = new UserDataForm();

        $model->scenario = 'create';

        

        if ($userDate->load(Yii::$app->request->post()) && $model->load(Yii::$app->request->post())) {

           

            

            $model->validate();

            $userDate->validate();

            

            $userDate->saveOptionalData();

            $model->RoyalUserData=$userDate->data['Id'];

            $model->saveUser();

            

            Yii::$app->session->setFlash('success', 'Użytkownik został dodany');

            return $this->redirect(['index']);

        } else {

            return $this->render('create', [

                        'model' => $model,

                        'userDate' => $userDate

            ]);

        }

    }

a w modelu:


 public function rules()

    {

        return [

            [['Address', 'Phone', 'Rel_State', 'Rel_Currency','IsCompany'], 'safe'],

            [['Address', 'Phone', 'Rel_State', 'Rel_Currency','IsCompany'], 'required',  'when' => function($model) {

    return $model->IsCompany();

}],

            [['NIP','IsCompany', 'Phone', 'IsPhoneConfirmed', 'CreatedAt', 'UpdateAt', 'Rel_State', 'Rel_Currency', 'IsDeleted'], 'integer'],

            [['Address', 'CompanyName', 'Website'], 'string', 'max' => 45],

            [['Phone'], 'common\components\validators\PhoneValidator'], 

            [['NIP'], 'common\components\validators\NipValidator'],

            ['IsCompany', 'safe']

        ];

    }

I teraz za każdym razem wymagane są pola z tego drugiego formularza nawet gdy checkbox jest odznaczony

Nie ma pojęcia, tak na sucho nic nie pomogę. Podepnij jakiegoś loga pod IsCompany() i sprawdź w jakim stanie jest model przy każdym wywołani tej metody.

Problem musi leżeć gdzie indziej bo nawet gdy ustawiam z buta ten atrybut na 1 lub 0 to i tak nie uwzględnia mi tego scenariusza:


 public function actionCreate() {

        $model = new UrUserForm();

        $userDate = new UserDataForm();

        $model->scenario = 'create';

        $userDate->IsCompany = 0;


        if (($userDate->load(Yii::$app->request->post()) && $userDate->IsCompany==1 && $model->load(Yii::$app->request->post()) && $model->validate())) {


            $userDate->scenario = 'setFirm';

            $userDate->validate();

            $userDate->saveOptionalData();

            $model->RoyalUserData = $userDate->data['Id'];

            $model->saveUser();

            

            Yii::$app->session->setFlash('success', 'Użytkownik został dodany');

            return $this->redirect(['index']);

        } else if ($userDate->load(Yii::$app->request->post()) && $userDate->IsCompany==0 && $model->load(Yii::$app->request->post()) && $model->validate()) {


            $userDate->scenario = 'notFirm';

            $userDate->validate();

            $userDate->clearData();

            $model->saveUser();


            Yii::$app->session->setFlash('success', 'Użytkownik został dodany');

            return $this->redirect(['index']);

        } else {

            return $this->render('create', [

                        'model' => $model,

                        'userDate' => $userDate

            ]);

        }

    }

i sprawzdałem dobrze wchodzi ten if bo gdy dodaję usera to sie zapissuje i gdy klinkę checkboxa, że to firma dodaje dodatkowe dane to też zapisuje użytkownika wraz z id do tabeli z dodatkowymi danymi. Problemem jest tylko ten scenariusz bo za każdym razem jest ustawiony na safe. Próbowałem już chyba wszystkeigo.