Yii transaction not rollbacked - php

i have the following piece of code and i pass it some data to generate an exception and test if the transaction rollback is happening. It seems it's not and i'm not sure why.
can someone help me? thanks
$transaction = Yii::app()->db->beginTransaction();
try {
//.....
//call private methods
$category = MyController::saveCategory($params);
$test_saved = MyController::saveTest($params);
MyController::saveCommunity($param); // here is an exception and it should rollback the transaction but it doesn't
$transaction->commit();
} catch(Exception $e) {
$transaction->rollback();
throw new Exception($e);
}
private function saveCommunity($param){
$community = new Community();
$community->user_id = $user_id;
$community->name = $name;
$community->id = 71; // this is a duplicate primary key and will generate an exception
try{
$community->save(false, null);
}catch(Exception $e){
throw $e;
}
return $community;
}
(mysql tables are set to innodb)

Try changing your code responsible for exception throwing:
try{
$community->save(false, null);
}catch(Exception $e){
throw $e;
}
to something like:
if(!$community->save(false, null))
throw new Exception('Error saving');
And remove the exception throwing here:
} catch(Exception $e) {
$transaction->rollback();
//throw new Exception($e);
}

By default pdo doesn't throw exceptions and just ignores errors.
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

Related

Can someone explain my how this exceptions works?

I found an really interesting problem on the internet about Exceptions & Errors, but I can't get it.
class MyException extends Exception {
public function __construct(string $message) {
$this -> message = $message;
}
}
class A {
public function __construct() {
throw new MyException("an error appeared");
}
}
$err = null;
try {
new A();
}
catch (MyException $err) {
throw new Exception('another error appeared');
}
catch (Exception $err) {
echo $err;
}
When I execute the code I receive
Fatal error: Uncaught Exception: another error appeared in C:\xampp
I don't understand if it's a problem about the code or this is how it works actually. Maybe you can help me.
That fatal error is for an untreated exception?
Thank you!
The second catch block does not catch the exception thrown in the first catch block. It can only be used to catch a an additional type of exception thrown in the first try block.
To catch your second exception you need to add a nested try catch:
try {
new A();
}
catch (MyException $err) {
try {
throw new Exception('another error appeared');
}
catch (Exception $err) {
echo $err;
}
}
Yes, the fatal error is for an unhandled exception here:
$err = null;
try {
new A();
}
catch (MyException $err) {
--->throw new Exception('another error appeared');
}
catch (Exception $err) {
echo $err;
}
In case you are wondering what is leading to this, it is this line in your code snippet:
$err = null;
try {
---> new A();
}

Can I use Doctrine transaction together with mysql PDO statements?

From below code I expect that $query1 will be undone after Exception is
thrown. But it's not.
try {
$this->em->getConnection()->beginTransaction();
PDO::exec($query1 = 'INSERT INTO foo...')
throw new Exception();
PDO::exec($query2 = 'INSERT INTO bar...')
$this->em->flush();
$this->em->getConnection()->commit();
} catch (\Exception $e) {
$this->em->getConnection()->rollBack();
throw $e;
}

How do I ensure all exceptions in this DB transaction are caught?

I use Yii and recently started using Transactions with try / catch blocks.
Here's how the code looks right now:
$dbConnection = Yii::app()->db();
try {
$transaction = $dbConnection->beginTransaction();
$dbConnection->createCommand("SELECT * from table_1")
->queryAll();
$transaction->commit();
} catch (Exception $ex) {
$transaction->rollback();
}
Suppose there's an exception with the DB (it's come up while unit-testing), I'm unable to rollback because the PHP dies with a fatal $transaction undefined error.
I'd rather not include isset() checks everywhere..
Is there a simpler way to make this work?
You can check if the exception is an instance of CDbException
$dbConnection = Yii::app()->db();
try {
$transaction = $dbConnection->beginTransaction();
$dbConnection->createCommand("SELECT * from table_1")
->queryAll();
$transaction->commit();
} catch (Exception $ex) {
if ($ex instanceof CDbException)
{
// handle CDBException
// ...
}
$transaction->rollback();
}

can't catch exception in codeIgniter

Sorry for my english but please i need help
i have a problem when i'm trying to catch an insert query
i have a table Employe with 3 primary keys (Matricule , CIN , name)
i want to catch the exception when i add a new employe with duplicated values
My Model
function insert_Employe($donnees){
try{
$this->db->insert('Employe',$donnees);
return 'employe enregistré avec succes';
}catch(Exception $e)
{
return $e->getMessage();
}
}
My controller
function nouveau(){
if(!$this->offres->_isLogged() || !$this->input->post('Ajax')==1){
redirect(base_url().'users');
}
$values = $this->_get_values();
try{
$message = $this->employe->insert_Employe($values);
echo $message;
}catch(Exception $e){
echo $e->getMessage();
}
}
i can't catch the exception
This will never throw an exception:
$this->db->insert('Employe',$donnees);
So you'll never catch an exception like that. If the insert() method fails it will generate display a custom error if $db['default']['db_debug'] is set to TRUE on database.config or simply return FALSE otherwise.
Your best bet is to check for errors when doing your DB operations:
$error = $this->db->_error_message()
if(!empty($error)) {
throw new Exception('Your message');
}

Is it possible to have Try/Catch Throw with multiple exceptions

i have the following code and i'm wondering if i can use try & catch as below:
class fun_database implements idbInfo{
private $srvr=idbInfo::srvr_name;
private $usr=idbInfo::usrnm;
private $pass=idbInfo::psswrd;
private $db=idbInfo::db_name;
public function connct(){
$hookup = new mysqli($this->srvr, $this->usr, $this->pass, $this->db);
if ($hookup->connect_errno)
{
throw new Exception("Error Processing Request", 1);
}
}
public function sql_require_all($table_name, $table_col){
$hookup = new connct();
$result = $hookup->query("SELECT $table_col FROM $table_name");
if($hookup->error()){
throw new Exception("Error Processing Request", 1);
}
return $result->num_rows;
}
}
This is a simple connection to the mysql and performing some querying there. Here is and the actual call of the functions above:
$conn = new fun_database();
try{
$result = $conn->sql_require_all('wordtypes', 'types');
}
catch(Exception $err){
echo "Problems at:". $err->getMessage();
}
return "<option>".$result."</option>";
What i'm asking is a bit theory. Most probably this code is NOT WORKING (i didn't test it yet). I just want to know is it possible with one 'try' to 'catch' two exceptions (as you can see the first 'throw' is in the second method of fun_database, and the second 'throw' is in the first method of the same object which is only called from the second method).
sorry for making it too complicated but still can't figure it out id this structure of try/catch is working.
you can only catch different types of exception...
class fun_database implements idbInfo{
private $srvr=idbInfo::srvr_name;
private $usr=idbInfo::usrnm;
private $pass=idbInfo::psswrd;
private $db=idbInfo::db_name;
public function connct(){
$hookup = new mysqli($this->srvr, $this->usr, $this->pass, $this->db);
if ($hookup->connect_errno)
{
throw new DomainException("Error Processing Request", 1);
}
}
public function sql_require_all($table_name, $table_col){
$hookup = new connct();
$result = $hookup->query("SELECT $table_col FROM $table_name");
if($hookup->error()){
throw new Exception("Error Processing Request", 1);
}
return $result->num_rows;
}
}
Then:
try{
$conn = new fun_database();
$result = $conn->sql_require_all('wordtypes', 'types');
}
catch(DomainException $err){
echo "This Problem at:". $err->getMessage();
}
catch(Exception $err){
echo "That Problem at:". $err->getMessage();
}
return "<option>".$result."</option>";
you would need your class instantiation inside that try block though I believe.
It wouldn't catch the two exceptions because as soon as the first exception is thrown, it goes straight to the catch block, thereby skipping the second exception directly.
You could wrap each code which may throw an exception in its own try-catch block.
Yes and no. Your code is able to catch two of this exceptions but not both of them at the same time. When one of exception will be thrown, program execution will look for closest catch block, which fits to catch Exception class. Rest of code will be omitted.
You can throw an exception at an point in the program (not after an excpetion if it is not caught).
As soon as it hits this point it will stop and try to make the fallback to the a try catch block. As soon as it finds one it will do this block (if it is a good catch)
You could make a try catch around your entire program or just a function.
You can throw different classes of exceptions:
class ConnectException extends Exception {}
class QueryException extends Exception {}
and then catch different exceptions:
try {
// something
}
catch (ConnectException $ex) {
// connect exception
}
catch (QueryException $ex) {
// query exception
}
It is not possible because when you throw
throw new Exception("Error Processing Request", 1);
this exception it will be caught in this line
catch(Exception $err){
echo "This Problem at:". $err->getMessage();
}
you will not reach the line that can throw the other exception if first exception was thrown

Categories