What are the best practices for handling database interactions in PHP classes to ensure clean and efficient code?

When handling database interactions in PHP classes, it is important to separate the database logic from the business logic to ensure clean and efficient code. One way to achieve this is by using dependency injection to pass a database connection object to the class, rather than creating the connection within the class itself. This allows for better code reusability, testability, and maintainability.

class DatabaseHandler {
    private $db;

    public function __construct($db) {
        $this->db = $db;
    }

    public function fetchData() {
        $query = "SELECT * FROM table";
        $result = $this->db->query($query);
        return $result->fetchAll();
    }

    public function insertData($data) {
        $query = "INSERT INTO table (column1, column2) VALUES (:value1, :value2)";
        $statement = $this->db->prepare($query);
        $statement->execute([
            'value1' => $data['value1'],
            'value2' => $data['value2']
        ]);
        return $this->db->lastInsertId();
    }
}

// Usage
$db = new PDO('mysql:host=localhost;dbname=test', 'username', 'password');
$databaseHandler = new DatabaseHandler($db);
$data = $databaseHandler->fetchData();
$newId = $databaseHandler->insertData(['value1' => 'foo', 'value2' => 'bar']);