We have moved our forum to GitHub Discussions. For questions about Phalcon v3/v4/v5 you can visit here and for Phalcon v6 here.

Only insert if both models dosent give error

How to do I stop one model from inserting if another model is failing?

I used this:

if ($robot->save() == false && $robot2->save == false) {
  echo "Umh, We can store robots: ";
  foreach ($robot->getMessages() as $message) {
echo message;
  }
 } else {
  echo "Great, a new robot was saved successfully!";
 }

But if one of the robots success, it will insert, but the other one wont insert.. How do i make them talk together?



7.0k

Use an array and iterate through it. When one robot can't be created or saved break the loop and so on.

Do you mind giving me an example code?

And thanks for answering :-)



7.0k

Sure. But it isn't tested.

$robots = array(/*there are your robots you wanna save laterly*/);
$allSaved = true;

foreach($robots as $robot) {
    if(!$robot->save()) {
        echo "Umh, we can't store robot: ";
        foreach($robot->getMessages() as $message) {
            echo $message;
        }

        $allSaved = false;

        break;
    }
}

if($allSaved) {
    echo "Great, a new robot was saved successfully!";
}


7.1k

Actually you're looking for a transaction. You can set the transaction before starting the loop and then rollback at the end if there are any failures, otherwise commit. See here: https://docs.phalcon.io/en/latest/api/Phalcon_Mvc_Model_Transaction.html

edited Jul '15

Thanks for the many answers.

The problem is still there - If Users fails, but Blogs succed, then it will still create a blog with the domain name giving. But no user will be created...

$this->db->begin();
$robot              = new \Users();
$robot->firstname        = "WALL·E";

if ($robot->save() == false) {
    foreach ($robot->getMessages() as $message) {
            echo $message, "\n";
    }
return;
}

                    $robotPart            = new \Blogs();
                    $robotPart->userid = $robot->id;
                    $robotPart->domain      = "domain";

                    if ($robotPart->save() == false) {
                        foreach ($robotPart->getMessages() as $message) {
        echo $message, "\n";
    }
}

$this->db->commit();


7.1k

You're not rolling back the transaction...you need to rollback in case of error. In fact, in the case of the blogs error, you're not even returning early, you're proceeding straight to the commit...

Hm, i don't seem to understand, could you make an example ?

When i put in $this->db->rollback() i get this error "There is no active transaction"



7.1k
                $this->db->begin();

                $robot              = new \Users();
                $robot->firstname        = "WALL·E";

                $robotPart            = new \Blogs();
                $robotPart->userid = $robot->id;
                $robotPart->domain      = "domain";

                if ($robot->save() == false) {
                    foreach ($robot->getMessages() as $message) {
                        echo $message, "\n";
                    }
                    return;
                }
                if ($robotPart->save() == false) {
                    foreach ($robotPart->getMessages() as $message) {
                        echo $message, "\n";
                    }
                    if ($this->db->isUnderTransaction()) {
                        $this->db->rollback();
                    }
                    return;
                }

                $this->db->commit();

Okay, i dont get the error from $RobotPart - Only if $robot success and i need all errors at once.. :-I



7.1k

So store the result of the save in a variable and check it at the end. Then rollback and return only at the end.

try {
    $this->db->begin();

    $robot              = new \Users();
    $robot->firstname        = "WALL·E";

    $robotPart            = new \Blogs();
    $robotPart->userid = $robot->id;
    $robotPart->domain      = "domain";

    if ($robot->save() == false) {
        foreach ($robot->getMessages() as $message) {
            throw new Exception((string) $message->getMessage());
        }        
    }

    if ($robotPart->save() == false) {
        foreach ($robotPart->getMessages() as $message) {
            throw new Exception((string) $message->getMessage());
        }
    }

    $this->db->commit();

} catch (\Exception $e) {
    $this->db->rollback();
    echo $e->getMessage();
}

Andres thanks for you answer, but that dosent solve my problem.. I need to insert only if robot and robotpart is success, and i need to display all the errors from robot and robotPart at once.. Your code only displays one error..