[Risolto] Transazioni Con Activerecord

Salve, qualcuno ha provato a fare delle transazioni via activerecord?

avrei bisogno di salvare più model, e devo essere certo che tutti i salvataggi avvengano correttamente.

ho provato un codice di questo tipo:




$transaction = Yii::app()->db->beginTransaction();

 

try {

    $user = new User();

    $user->username = $form->username;

    $user->password = $form->password;

    $user_save = $user->save(FALSE);

 

    $user_info = new UserInfo();

    $user_info->name = $form->name;

    $user_info->user = $user->id;

    $user_info->age = $form->age;

    $user_info_save = $user_info->save(FALSE);

   

    if($user_save && $user_info_save){

        $transaction->commit();

    } else {

        $transaction->rollBack();

    }

} catch(Exception $e) {

    $transaction->rollBack();

}



in questa maniera però, provando lato controller a inserire valori manualmente, ad esempio, valori testuali in campi int, la transazione avviene ugualmente, lasciando vuoto il campo int nel db perchè permette valori null.

nel caso,ad esempio, io inserisca valori numerici che violino una foreign key… a quel punto vedo l’errore.

la domanda è. non c’è un modo che la transazione passi prima la validazione yii e poi anche i vincoli del db. ora va solo per la seconda questione, e il db nel caso arrivino caratteri al posto di un int non genera un’eccezione ma lascia il campo vuoto.

hai bloccato la validazione prima di eseguire il save, è normale che lui non veda le regole dei model.

togli quei false ed hai risolto il tuo problema.

Già fatto, ma purtroppo non agisce come dovrebbe. Oggi ero un pò bollito quando stavo scrivendo questo codice, quindi mi sono ripromesso di riguardarlo domani mattina con calma.

Voi avete mai provato qualcosa di simile, io voglio che 3-4 blocchi di istruzioni vadano tutti a buon fine altrimenti rollback!

purtroppo, per il codice che ho testato io, questo non riuscivo a farlo.

Anche togliendo i false, alcuni model venivano salvati correttamente nonostane alcune istruzioni dopo non andavano a buon fine.

Il codice che ho postato è di esempio,trovato a giro, domani se dovessi continuare ad avere problemi, vi posto il mio. Intanto se avete casi d’uso simili o consigli, vi ringrazio!

Esegui le query in questo modo. Non usare normalmente i tuoi model.

ora sto facendo dei test. chiaramente in sql statetement risolvo il problema.

E’ che come consigli spesso tu sul forum, uno si pone problemi solo quando li ha.

Allora visto che per ora ne ho uno, devo capirne le potenzialità di un codice tipo quello che ho postato,

così la prossima volta non ci perdo tempo ;)

confermo che un codice come suggeriva nickcv, sembra fare il suo dovere.

Questa mattina ho rivisto tutti i model interessati, le varie rules, e alla fine sembra andare.

In questa maniera si può usare la validazione yii e quella del db per fare eseguire tutta la transazione.

Preferivo più una soluzione del genere perchè devo utilizzarla su differenti action, e sinceramente l’sql

è meno usabile, senza contare la doppia validazione che ho su un codice di questo tipo.




$transaction = Yii::app()->db->beginTransaction();

try {

    $user = new User();

    $user->username = $form->username;

    $user->password = $form->password;

    $user_save = $user->save();

 

    $user_info = new UserInfo();

    $user_info->name = $form->name;

    $user_info->user = $user->id;

    $user_info->age = $form->age;

    $user_info_save = $user_info->save();

   

    if($user_save && $user_info_save){

        $transaction->commit();

    } else {

        $transaction->rollBack();

    }

} catch(Exception $e) {

    $transaction->rollBack();

}



bravo ragazzo!

oltretutto seguendo il consiglio di sensorario avresti perso del tutto ogni vantaggio datoti da active record.

ad ogni modo per rendere il codice più chiaro io lo modificherei leggermente rendendolo così:




$transaction = Yii::app()->db->beginTransaction();

try {

    $user = new User();

    $user->username = $form->username;

    $user->password = $form->password;

    $user_save = $user->save();

 

    $user_info = new UserInfo();

    $user_info->name = $form->name;

    $user_info->user = $user->id;

    $user_info->age = $form->age;

   

    if(!$user_save || !$user_info->save()){

        throw new Exception('could not save on db');


    $transaction->commit();

} catch(Exception $e) {

    $transaction->rollBack();

}



in questa maniera hai un solo commit ed un solo rollback rendendolo più leggibile.

poi volendo essere pignoli potresti wrappare tutta sta roba in un servizio in maniera tale che il controller faccia giustamente solo il suo lavoro di passacarte

Grazie per i consigli e del supporto.

Buon lavoro.