Greetings all, I’m looking for a more efficient way to grab multiple users without too much code redundancy.
I have a Users class, (here’s a highly condensed representation)
Class Users {
function __construct() { ... ... }
public static function getNew($id) {
// This is all only example code
$sql = "SELECT Name,Email,Etc.. FROM Users WHERE User_ID=?";
// Retrieval using prepared statements would go here
$user = new User();
$user->setID($id);
....
return $user;
}
public static function getNewestUsers($count) {
$sql = "SELECT User_ID,Name,Email,Etc.. FROM Users ORDER BY Join_Date LIMIT ?";
$users = array();
// Prepared Statement Data Here
$stmt->bind_result($id,$name,$email,$etc);
while($stmt->fetch()) {
$users[] = Users::getNew($id);
...
}
return $users;
}
// These have more sanity/security checks, demonstration only.
function setID($id) { $this->id = $id; }
function setName($name) { $this->name = $name; }
...
}
So clearly calling getNew() in a loop is inefficient, because it makes $count number of calls to the database each time. I would much rather select all users in a single SQL statement.
The problem is that I have probably a dozen or so methods for getting arrays of users, so all of these would now need to know the names of the database columns which is repeating a lot of structure that could always change later.
What are some other ways that I could approach this problem? My goals include efficiency, flexibility, scalability, and good design practice.
Simplification of boilerplate SQL binding
This isn’t so much a solution as a suggestion:
You’re running pretty bare to the metal here as far as sql. I recommend separating your sql out a bit more, one way that I’ve found useful is creating a simple database abstraction library function, let’s call it
query. Using Mikushi’s example above:Ideal usage, going off of how binding works with PDO because I’m not really familiar with the binding method for mysql_fetch_assoc()
That has three benefits: simpler binding, not having to do boiler-plate for single or multi-row select statements (an 80%-of-the-time use case), and potentially an easier time if you ever need to switch databases.
Factory Pattern to Separate Creation of User objects from modification
As far as the original issue of user creation, how about using the factory pattern to separate the creation of
Userobjects from the methods thatUserobjects can perform on their own data?Use:
The user object would then only: use __constructor() on an array of data as Mikushi mentions, and perform alterations on that data (which the factory could potentially have a
function saveUser($user_object)to save changes.