Using Exceptions

Using Exceptions in MySQLi
Exception handling is a crucial aspect of modern programming languages, providing a way to manage errors and other exceptional conditions in a structured manner. In PHP, the MySQL Improved (MySQLi) extension supports exception handling in an object-oriented programming (OOP) style.
This article explores how to use exceptions in MySQLi, covering various techniques to handle errors efficiently, and providing code examples to illustrate these concepts.

What Are Exceptions?

Exceptions are objects that represent an error or an unusual condition in a program. When an exception is thrown, the normal flow of the program is interrupted, and the control is transferred to an exception handler. This allows for a clean separation of error-handling logic from regular code, improving readability and maintainability.

Setting Up MySQLi with Exceptions

To use exceptions with MySQLi, you first need to enable the exception mode. This can be done using the mysqli_report function.

Code Example: Enabling Exception Mode

				
					<?php
mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);

$servername = "localhost";
$username = "root";
$password = "password";
$dbname = "mydatabase";

try {
    $conn = new mysqli($servername, $username, $password, $dbname);
    echo "Connected successfully";
} catch (mysqli_sql_exception $e) {
    die("Connection failed: " . $e->getMessage());
}
?>

				
			
In this code:
  • mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT) configures MySQLi to throw exceptions on errors.
  • The try block contains the code that might throw an exception.
  • The catch block handles the exception, outputting an error message if the connection fails.

Handling Exceptions in MySQLi

Handling exceptions effectively is essential for creating robust applications. Below are various techniques for handling exceptions in MySQLi.

1. Basic Exception Handling

In the simplest form, exception handling involves wrapping MySQLi operations in a try-catch block.

Code Example: Basic Exception Handling

				
					<?php
mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);

try {
    $conn = new mysqli($servername, $username, $password, $dbname);
    
    $sql = "SELECT id, firstname, lastname FROM MyGuests";
    $result = $conn->query($sql);

    while ($row = $result->fetch_assoc()) {
        echo "id: " . $row["id"]. " - Name: " . $row["firstname"]. " " . $row["lastname"]. "<br>";
    }
} catch (mysqli_sql_exception $e) {
    echo "Error: " . $e->getMessage();
} finally {
    $conn->close();
}
?>

				
			
In this example:
  • The try block contains the database operations.
  • The catch block catches any mysqli_sql_exception and displays an error message.
  • The finally block ensures the database connection is closed.

2. Handling Specific Exceptions

You might want to handle different types of exceptions differently. PHP allows you to catch specific exception types and handle them accordingly.

Code Example: Handling Specific Exceptions

				
					<?php
mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);

try {
    $conn = new mysqli($servername, $username, $password, $dbname);
    
    $sql = "SELECT id, firstname, lastname FROM MyGuests";
    $result = $conn->query($sql);

    while ($row = $result->fetch_assoc()) {
        echo "id: " . $row["id"]. " - Name: " . $row["firstname"]. " " . $row["lastname"]. "<br>";
    }
} catch (mysqli_sql_exception $e) {
    if ($e->getCode() == 1045) { // Example error code for access denied
        echo "Authentication error: " . $e->getMessage();
    } elseif ($e->getCode() == 2002) { // Example error code for connection failure
        echo "Connection error: " . $e->getMessage();
    } else {
        echo "Database error: " . $e->getMessage();
    }
} finally {
    $conn->close();
}
?>

				
			
In this example:
  • Different types of mysqli_sql_exception are handled based on the error code.

3. Using Custom Exception Handlers

For more advanced error handling, you can create custom exception handlers. This approach allows you to encapsulate error-handling logic in a dedicated class, improving code organization and reusability.

Code Example: Custom Exception Handler

				
					<?php
class DatabaseException extends Exception {}

class Database {
    private $conn;

    public function __construct($servername, $username, $password, $dbname) {
        mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
        
        try {
            $this->conn = new mysqli($servername, $username, $password, $dbname);
        } catch (mysqli_sql_exception $e) {
            throw new DatabaseException("Database connection failed: " . $e->getMessage(), $e->getCode());
        }
    }

    public function query($sql) {
        try {
            $result = $this->conn->query($sql);
            return $result;
        } catch (mysqli_sql_exception $e) {
            throw new DatabaseException("Query failed: " . $e->getMessage(), $e->getCode());
        }
    }

    public function __destruct() {
        $this->conn->close();
    }
}

try {
    $db = new Database($servername, $username, $password, $dbname);
    $result = $db->query("SELECT id, firstname, lastname FROM MyGuests");

    while ($row = $result->fetch_assoc()) {
        echo "id: " . $row["id"]. " - Name: " . $row["firstname"]. " " . $row["lastname"]. "<br>";
    }
} catch (DatabaseException $e) {
    echo "Error: " . $e->getMessage();
}
?>

				
			
In this example:
  • DatabaseException is a custom exception class.
  • Database is a class that encapsulates the database connection and query logic.
  • The try-catch block catches DatabaseException and handles it accordingly.

4. Logging Exceptions

Logging exceptions is a best practice for monitoring and debugging applications. PHP’s error_log function can be used to log exception details.

Code Example: Logging Exceptions

				
					<?php
class DatabaseException extends Exception {}

class Database {
    private $conn;

    public function __construct($servername, $username, $password, $dbname) {
        mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
        
        try {
            $this->conn = new mysqli($servername, $username, $password, $dbname);
        } catch (mysqli_sql_exception $e) {
            $this->logError($e);
            throw new DatabaseException("Database connection failed: " . $e->getMessage(), $e->getCode());
        }
    }

    public function query($sql) {
        try {
            $result = $this->conn->query($sql);
            return $result;
        } catch (mysqli_sql_exception $e) {
            $this->logError($e);
            throw new DatabaseException("Query failed: " . $e->getMessage(), $e->getCode());
        }
    }

    private function logError($e) {
        $log = "Error: [" . $e->getCode() . "] " . $e->getMessage() . " - " . $e->getFile() . ":" . $e->getLine() . PHP_EOL;
        error_log($log, 3, 'errors.log'); // Log error to a file
    }

    public function __destruct() {
        $this->conn->close();
    }
}

try {
    $db = new Database($servername, $username, $password, $dbname);
    $result = $db->query("SELECT id, firstname, lastname FROM MyGuests");

    while ($row = $result->fetch_assoc()) {
        echo "id: " . $row["id"]. " - Name: " . $row["firstname"]. " " . $row["lastname"]. "<br>";
    }
} catch (DatabaseException $e) {
    echo "Error: " . $e->getMessage();
}
?>

				
			
In this example:
  • logError method logs the exception details to a file named errors.log.

Using Transactions with Exception Handling

Transactions ensure that a series of database operations are executed as a single unit. If any operation fails, the transaction can be rolled back, ensuring data integrity. Combining transactions with exception handling provides a robust way to manage database operations.

Code Example: Transactions with Exception Handling

				
					<?php
class DatabaseException extends Exception {}

class Database {
    private $conn;

    public function __construct($servername, $username, $password, $dbname) {
        mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
        
        try {
            $this->conn = new mysqli($servername, $username, $password, $dbname);
        } catch (mysqli_sql_exception $e) {
            $this->logError($e);
            throw new DatabaseException("Database connection failed: " . $e->getMessage(), $e->getCode());
        }
    }

    public function query($sql) {
        try {
            $result = $this->conn->query($sql);
            return $result;
        } catch (mysqli_sql_exception $e) {
            $this->logError($e);
            throw new DatabaseException("Query failed: " . $e->getMessage(), $e->getCode());
        }
    }

    public function beginTransaction() {
        $this->conn->begin_transaction();
    }

    public function commit() {
        $this->conn->commit();
    }

    public function rollback() {
        $this->conn->rollback();
    }

    private function logError($e) {
        $log = "Error: [" . $e->getCode() . "] " . $e->getMessage() . " - " . $e->getFile() . ":" . $e->getLine() . PHP_EOL;
        error_log($log, 3, 'errors.log'); // Log error to a file
    }

    public function __destruct() {
        $this->conn->close();
    }
}

try {
    $db = new Database($servername, $username, $password, $dbname);
    $db->beginTransaction();

    $db->query("INSERT INTO MyGuests (firstname, lastname, email) VALUES ('John', 'Doe', 'john.doe@example.com')");
    $db->query("INSERT INTO MyGuests (firstname, lastname, email) VALUES ('Jane', 'Doe', 'jane.doe@example.com')");

    $db->commit();
    echo "New records created successfully";
} catch (DatabaseException $e) {
    $db->rollback();
    echo "Transaction failed: " . $e->getMessage();
}
?>

				
			
In this example:
  • beginTransaction, commit, and rollback methods are used to manage transactions.
  • If an exception occurs, the transaction is rolled back, ensuring data integrity.

Conclusion

Exception handling in MySQLi using an object-oriented approach is essential for building robust, maintainable, and secure applications. This article covered various techniques for handling exceptions, including basic and specific exception handling, custom exception handlers, logging exceptions, and using transactions with exception handling. By following these best practices and utilizing the provided code examples, you can ensure that your PHP applications handle database errors effectively, improving both the user experience and the overall stability of your applications.
Scroll to Top