Handling database errors

Hello.

I have a doubt about how i do for handling database errors on YII2.

I have an gii app called Ambientes that interact with the ambientes table.

Ambientes table have child’s on SapAmbientes table (1 to N relationship).

When I delete on Ambientes a record who have child, displays an default error on routed default page. I don’t want this. I need to redirect it to app who’s call, and simple add a flash message (or similar) on this (view or index) views.

I already did research for a few days, has some solutions for yii1 but I did not find anything that works on yii2.

I would like to know of the veterans how do the bank exception handling not to divert to that generic error page in YII2.

I made some changes, but it didn’t look nice.

Table Environments 1 - N Table SapAmbientes

Where I put on a model class called Ambientes


Public function beforeDelete ()

{

  $ P = new \ app \ models \ SapPerfis ();

  \ Yii :: $ app-> getSession () -> remove ('deleteAmbientes');

  $ Return = $ p :: find () -> where (['environment' => $ this-> environment]) -> one ();

  If ($ return! == null) {

         \ Yii :: $ app-> getSession () -> setFlash ('deleteAmbientes', Yii :: t (' app ',' Can not delete this record. ') There are some dependents records.'));

         Return FALSE;

  } Else { 

      Return TRUE;

  }

}



on a controller I modified the actionDelete


<font face="Courier New">Public function actionDelete ($ id)

{

  If (! Yii :: $ app-> user-> can ('deleteAmbientes'))

        Throw new ForbiddenHttpException;

  $ Record = $ this-> findModel ($ id);

   If ($ record! == null) {

      Try {

 		$ Ret = $ record-> delete ();

 		If ($ ret === FALSE) {

       		If (\ Yii :: $ app-> getSession () -> hasFlash ('deleteAmbientes')) {

              Return $ this-> render ('view', ['Model' => $ this-> findModel ($ id),

        ]);

      }

   }

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

} Catch (\ ErrorException $ e) {

 		Yii :: warning ("The record can not be deleted.");

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

}

}


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

}

</font>

And on the view I put


<font face="Courier New"><? = (\ Yii :: $ app-> getSession () -> hasFlash ('deleteAmbientes')?

'<Div class = "alert-danger"> <p class = "error-summary">'

. \ Yii :: $ app-> getSession () -> getFlash ('deleteAmbientes')

. ' (<a href="javascript:history.back(-1)" class="backLink"> '

.Yii :: t ('app', 'Return previous page')

. ') </a> </ p> </ div>'

(I.e.

)?></font><div>

For now it works, but I have to make the error code validation, rather than just redirect a database error.

How do you do for such treatment?

What’s the error message?

[color=#E51717][font=inherit][size=2]Integrity constraint violation[/size][/font][/color] – yii\db\IntegrityException

[b]SQLSTATE[23000]: Integrity constraint violation: 1451 Cannot delete or update a parent row: a foreign key constraint fails (adv_perfis.sap_perfis, CONSTRAINT sap_perfisxambientes_FK FOREIGN KEY (ambiente) REFERENCES ambientes (ambiente) ON DELETE NO ACTION ON UPDATE CASCADE)

The SQL being executed was: DELETE FROM ambientes WHERE ambiente=‘ECC’[/b]

The question I bring is not exactly an error message, it is procedural.

What happens is that, by default, when an exclusion error in a database (which is treatable) occurs, yii automatically redirects to Exception page (production mode) or throws an exception (developer mode).

What I do not want is to redirect the error through yii’s automatic processes. I need to handle this error in the view itself that requested the deletion.

I see this code on a forum, but i can’t do its work.

[font="arial, sans-serif"][size=3]


    'on afterAction' => function ($event) {

        $exception = Yii::$app->errorHandler->exception;

        if ($exception instanceof \yii\db\IntegrityException) {

            $event->handled = true;

            Yii::$app->getSession()->setFlash('danger', 'Este registro é referenciado e não pode ser excluído.');

            return Yii::$app->getResponse()->redirect(Yii::$app->request->referrer)->send();

        }

    },



[/size][size="3"]maybe I put on wrong place.[/size][/font]

[font="arial, sans-serif"][size="3"]maybe exists extra configuration to this works.[/size][/font]

[font="arial, sans-serif"] [/font]

[font="arial, sans-serif"] [/font]

Since Yii throws exceptions you can catch these:




try {

    // your DB query

} catch (\yii\db\IntegrityException $e) {

    // do error handling

}



1 Like

I just had the same problem and here is how I made it work.
You can place the code in web.php - just before 'params' => $params, line
but to get the flash you need to comment out
//defined('YII_DEBUG') or define('YII_DEBUG', true); line
in index.php. Otherwise you will get debug output (no flash).