yii2事务没有回滚

时间:2017-12-04 12:50:16

标签: php transactions yii2

我正在尝试在我的代码中实现事务。但即使在其中一个模型($ timesheet模型)验证失败后,事务也不会回滚。 以下是我的代码:

public function actionCreate() {
    $model = new Timesheet();
    $subscriber = null;
    // get current subscriber id.
    $subscriber_id = General::getSubscriberIdByUserId(\Yii::$app->user->id);
    if ($subscriber_id > 0) {
        $subscriber = Subscriber::findOne($subscriber_id);
        if ($subscriber) {
            $model->subscriber_id = $subscriber->id;
            $model->subscriber_name = $subscriber->name;
        }
    }

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

        //Transaction starts here
        $transaction = Yii::$app->db->beginTransaction();
        try
        {
            if (!empty($model->date)) {
                $model->date = General::convertDDMMYYYYToMysqlCompliant($model->date);
                $model->user_id = \Yii::$app->user->id; 
            }

            // to find total hours of the day already logged            
            $total_daily_hours = (Timesheet::find()->where(['user_id' => Yii::$app->user->id])->andWhere(['date' => $model->date])->sum('hours'));

            $model->hours = ($model->hours + $model->minute);
            $dayofweek = date('w', strtotime($model->date));
            if($dayofweek == 6)
            {
                $monday = date('Y-m-d', strtotime('last monday', strtotime($model->date)));
            }
            else
            {
                $monday = date('Y-m-d', strtotime('this monday', strtotime($model->date)));
            }
            $saturday = date('Y-m-d', strtotime('this saturday', strtotime($model->date)));

            // to find total hours of the week already logged
            $team_member_weekly_hours = Timesheet::find()->where(['user_id' => \Yii::$app->user->id])->andWhere(['between', 'date', $monday, $saturday])->sum('hours');

            $role = \Yii::$app->authManager->getRolesByUser(\Yii::$app->user->id);

            if(array_key_exists('intern', $role) == false)
            {
                $TEAM_MEMBER_WEEK_LIMIT = 48;
            }
            else
            {
                $TEAM_MEMBER_WEEK_LIMIT = Timesheet::TEAM_MEMBER_WEEK_LIMIT;
            }

            if ((
                    (Timesheet::PER_DAY_HOURS_LIMIT) >= ($total_daily_hours + $model->hours) 
                    || ((Timesheet::PER_DAY_HOURS_LIMIT) >= ($total_daily_hours + $model->hours) 
                        && (array_key_exists('team-member', $role)))
                ) 
                && (Timesheet::blockMonthEntry($model->date) == true) 
                && ($TEAM_MEMBER_WEEK_LIMIT >= $team_member_weekly_hours + $model->hours)
                && ($model->hours != 0))
            { 
                // get user hourly rate
                $usertohourlyrate = UserToHourlyRate::getHourlyRateByUserId($model->user_id);
                $model->total_amount = $usertohourlyrate * $model->hours;
                $model->hourly_rate = $usertohourlyrate;

                // echo "<pre>";var_dump($model);die;

                if($model->save())
                {
                    $model_id = $model->id;
                }
                // echo "$model_id";

                //For Notification
                $userToNotify = [];
                $user_id = \Yii::$app->user->id;
                $userForNotify = UserToSubscriber::find()->select('senior_user_id')->where(['user_id'=>$user_id])->all();

                if($userForNotify != NULL)
                {                     
                    $userToNotify = [];
                    foreach($userForNotify as $ufn){
                        array_push($userToNotify,$ufn->senior_user_id);
                    }

                    foreach($userToNotify as $value)
                    {                           
                        $noticemodel = new Notifications();
                        $noticemodel->user_id = $value;
                        $noticemodel->relation_name = 'timesheet';
                        $noticemodel->relation_id = $model->id;
                        $noticemodel->notice_abstract = "Timesheet Created Notification.";
                        $noticemodel->action = '0';
                        $noticemodel->created_on = date('Y-m-d h:i:s');                            
                        $noticemodel->save();
                    }
                }
                //

                if (General::ifUserPermitted('timesheetAutoTimesheetApproval')) {
                    // echo "in if";
                    // timesheet auto approval 
                    // WIP update
                    General::onTimesheetChange($model->job_id, $model->user_id, $model->date, "timesheet");
                    //For update timesheet model
                    $timesheet_model = Timesheet::findOne($model_id);
                    echo "<pre>";var_dump($timesheet_model);//die;
                    $timesheet_model->action_taken_at = date("Y-m-d h:m:s");
                    $timesheet_model->action_taken_by = \Yii::$app->user->id;
                    $timesheet_model->status = "Approved";  
                    echo "<pre>";var_dump($timesheet_model);                
                    $timesheet_model->save();
                    if($timesheet_model->save())
                    {
                        echo "True";
                    }
                    else
                    {
                        echo "False";
                        $errors = $timesheet_model->errors;
                        echo "<pre>";var_dump($errors);
                    }
                    //For Notification
                    if($userForNotify != NULL)
                    {
                        $userToNotify = [];
                        foreach($userForNotify as $ufn){
                            array_push($userToNotify,$ufn->senior_user_id);
                        }

                        foreach($userToNotify as $value)
                        {
                            $notification = Notifications::find()->where(['user_id'=>$value , 'relation_id'=>$model->id, 'notice_abstract'=>'Timesheet Created Notification.'])->one();
                            if($notification != NULL)
                            {
                                $notification->action = '1';
                                $notification->save();            
                            }
                        }
                    }                    
                    //
                }
                if (array_key_exists('team-member', $role)) {
                    $msg = "Entry Inserted Successfully and Your remaining weekly hours is <b>" . ((Timesheet::TEAM_MEMBER_WEEK_LIMIT) - ($team_member_weekly_hours + $model->hours)) . " hrs.</b>";
                } else {
                    $msg = "Entry Inserted Successfully and Your remaining hours is <b>" . ((Timesheet::PER_DAY_HOURS_LIMIT) - ($totel_hours + $model->hours)) . " hrs.</b>";
                }
                \Yii::$app->session->setFlash('success', $msg);

                $transaction->commit();

                return $this->redirect(['view', 'id' => $model->id]);

            }
            elseif (Timesheet::blockMonthEntry($model->date) != true) {
                $msg = "This date has been blocked";
            }elseif ($totel_hours == (Timesheet::PER_DAY_HOURS_LIMIT) || $team_member_weekly_hours == (Timesheet::TEAM_MEMBER_WEEK_LIMIT)) {                
                $msg = "Your Daily hours is over";
            } elseif (($totel_hours + $model->hours) > Timesheet::PER_DAY_HOURS_LIMIT) {
                $msg = "Your remaining daily hours only is <b>" . ((Timesheet::PER_DAY_HOURS_LIMIT) - $totel_hours) . " hrs.</b>";
            } elseif ($model->hours == 0) {
                $msg = "Please select hours";
            } else {
                $msg = "Your remaining Weekly hours only is <b>" . ((Timesheet::TEAM_MEMBER_WEEK_LIMIT) - $team_member_weekly_hours) . " hrs.</b>";
            }
            \Yii::$app->session->setFlash('error', $msg);
            list($model->hours, $minute) = explode('.', $model->hours);
            $model->minute = "0." . $minute;

            if(empty($model->date)){
                $model->date = date('j/n/Y');
            }else{
                $model->date = General::convertMysqlDateToDDMMYYYY($model->date);
            }
            return $this->render('create', [
                        'model' => $model,
                        'master_mode' => Yii::$app->user->can('associateSubscriberWithDetails'),
            ]);
        }
        catch(Exception $e)
        {
            \Yii::$app->session->setFlash('error', $e);
            $transaction->rollBack();
        }
        //Transaction ends here
    }
    else
    {
        if(empty($model->date)){
            $model->date = date('j/n/Y');
        }else{
            $model->date = General::convertMysqlDateToDDMMYYYY($model->date);
        }

        return $this->render('create', [
                    'model' => $model,
                    'master_mode' => Yii::$app->user->can('associateSubscriberWithDetails'),
        ]);
    }
}

我该怎么办?在哪里修改代码? $ timesheet模型在更新模型时失败,但模型在未回滚之前保存。

如果任何一个模型save()失败,我想回滚所有save()。

1 个答案:

答案 0 :(得分:0)

当执行此方法失败时,Yii save()不会抛出异常(对于异常)。因此,您必须检查save()的结果,并在发生故障时抛出异常。

save()语句中使用try{}catch(Exception $e){}时,请使用此处:

if (!$model->save()) {
   throw new Exception("Trigger transaction rollback");
} else {
    // something
}