A beginner question: I don't know how best to structure this bit of code, but basically it goes like this (pseudo code time):
if (form = submitted) {
submitted();
}
else {
printForm();
}
function submitted() {
process data from form;
if(errors = found) {
print warnings;
printForm();
} else {
submit to database;
}
}
function printForm() {
print form with databound elements;
}
I use the following bit of code to create a User object, but it seems weird to call it twice -- once in submitted()
and once in printForm()
, especially since submitted()
calls printForm()
if errors are found.
Unfortunately database access is required for processing the data from the form (checking for existing email address, etc), so I have to call the following bit of code in both submitted()
and printForm()
...
try {
$db = new Database();
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$user = new User($db);
}
catch (PDOException $e) {
echo "<p>Error connecting to database: </p>".$e->getMessage();
}
But my instincts tell me that this is bad. Is it? If so, how should I fix it?
Use dependency injection:
function submitted(Database $db, User $user) {
// ...
}
function printForm(Database $db, User $user) {
// ...
}
try {
$db = new Database();
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$user = new User($db);
}
catch (PDOException $e) {
echo "<p>Error connecting to database: </p>".$e->getMessage();
}
submitted($db, $user);
printForm($db, $user);
Of course, it's better to use OOP, as then you wouldn't have to inject the dependencies into every single function:
class Foo {
protected $db;
protected $user;
public function __construct(Database $db, User $user) {
$this->db = $db;
$this->user = $user;
}
public function submitted() {
// use $this->db and $this->user here
}
public function printForm() {
// use $this->db and $this->user here
}
}
try {
$db = new Database();
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$user = new User($db);
$foo = new Foo($db, $user);
}
catch (PDOException $e) {
echo "<p>Error connecting to database: </p>".$e->getMessage();
}
$foo->submitted();
$foo->printForm();
There are several ways of making this better...
One would be to initialize $user before the function calls and inject it into each function (dependency injection).
Another way would be to make a singleton of the user instance (although I could see this leading to problems down the road) and retrieve the instance in the function using something like User::instance()
.
Dependency injection is better in my opinion because it makes your functions easier to test.
Now, on to the rest of the code:
Although the Singleton pattern is considered to be evil in some cases, it seems that in PHP (with a separate worker process for each request) and in your case it is the easiest way to implement what you want.
So that you have the instance of User
who initiated the request available in any script on any page, and you have to initialize the $user
object only in one place per project (not in one per script as you were wanting to do).