Let me start off by saying I am not new to PHP or PDO, but very new to OO PHP, and have been struggling to get a firm idea of best practices in my head regarding dependency injection and structuring my classes and their methods.
The code I am providing will clearly be built on once I know I am doing things the correct way, so imagine more methods etc. using the same techniques I have used below, and what needs to be changed to make the whole package efficient and stable.
Whilst I am working on other PHP projects at work, the code below is not for or from any project, simply to help me learn before using OO in a real project. I also would normally do far more error checking, checking variables are set etc but have fiddled with this code so much, I haven't done this yet.
Here are the issues I see with it:
- It seems that I am not taking advantage of the extra efficiency prepared statements bring when re-using the same statement but with different values. By doing this in a method like below, I would be preparing the statement every time, even if I just wanted to change the values.
- I am not using a dependency injection container. Whilst it may not be necessary for small classes like these, I feel it would be better to use on in the long run.
- I am worried I am on the track to creating tonnes of methods for every different type of query - see the
findById
andreturnObjectById
methods - they are structured very differently - one calling a query method in theDatabase
class, the other running the query within theUser
class - I have no idea which is best. But also I feel I could end up creating a new page, realizing I need ANOTHER type of query, and then having to either write one in that file as a single instance (which would make me think why don't I do this for all), or create ANOTHER method in theUser
orDatabase
class. - Are my methods within the correct classes - should the
returnObjectById
for example, be in the database class?
Note: Classes are auto loaded with spl_autoload_register
in the config file, where DB constants are also set.
class_Database.php
class Database
{
private $conn;
public function __construct() {
$this->openConnection();
}
public function getConnection()
{
$conn = $this->conn;
return $conn;
}
public function openConnection() {
try {
$this->conn = new PDO('mysql:host=' . DB_SERVER . '; dbname=' . DB_NAME, DB_USER, DB_PASS);
$this->conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
} catch (PDOException $e) {
echo 'There was an error connecting to the database, Error: ' . $e->getMessage();
die();
}
}
public function standardQuery($sql, array $params)
{
$stmt = $this->conn->prepare($sql);
$stmt->execute($params);
return $stmt->fetch(PDO::FETCH_ASSOC);
}
}
class_User.php
class User
{
public $id;
public $first_name;
public $last_name;
public $username;
public $password;
public function __construct()
{
}
public function findById(Database $db, $id)
{
$user = $db->standardQuery("SELECT * from users WHERE id = :id", array(':id' => $id));
return $user;
}
public function returnObjectById(Database $db, $id)
{
$stmt = $db->getConnection()->prepare("SELECT * from users where id = :id");
$stmt->bindParam(':id', $id);
$stmt->execute();
return $stmt->fetchAll(PDO::FETCH_CLASS, "User");
}
}
Essentially, answers to my points above would be great, but I'd like to know if I am in any way moving in the right direction, or if I should stop and start over with a different technique.