So I've just started coding in classes and I haven't quite got my head around it yet. So I understand the concept of OOP but I have a question.
I have "users" stored in a database, and I want a user class that will get information I might want about a user and do things related to a "user" object. I understand that.
So say I have a user class, with properties username and email I have the following code
<?php
class User {
private $username;
private $email;
public function __construct($username,$email) {
$this->username=$username;
$this->email=$email;
}
}
?>
Now I know I should have getters and setters to access username and email. Getters, I understand. But setters - do I need these? And if I do, should these update that field in the database for that user? Would my setter for email update the database as well as the $this->email ? It may seem like a silly question but I want to get this right.
Then finally what is the best way to get users from the database and create objects? Say elsewhere I want to create a user object from ID 50 - which would get user with ID 50 from the database and construct a user object with the database email and username fields, what is the best way to do this?
Thanks!
But setters - do I need these?
It depends. If you do not have to do anything more than setting the property, you may not use one. You can ohwever need one if you need to check if the provided value matches, for example, a reg exp, or isn't too long/short, etc. You might also need one if you have setters for other properties and want to keep a uniform interface not to remember which property has or hasn't a setter.
And if I do, should these update that field in the database for that user?
If you are to modify several properties, it is better to only access the database a single time. Some database abstraction libraries do it that way :
$user->name = 'whatever';
$suer->email = 'whatever';
$user->save(); // Execute the modify query.
Accessing/modifying data in a database is expensive.
Then finally what is the best way to get users from the database and create objects?
If you are using, for example, mysql, you can use :
$users = [ ];
while($row = $result->fetch_assoc()) {
$user = new User;
foreach($row as $field => $value) {
$user->$field = $value;
}
$users[] = $user;
}
But there might be more elegant ways to do that though.
Setters are used to set object properties values and in most cases this is it. There are many ways of achieving what you want and basically there are books written about that. I personally tend to have a scenario like follows:
1) Set object properties using setters
2) Call a separate function commit()/save()/whatever() that will write all values to the database
As of creating an object from a row, you'd better have separate factory classes (nice question and answer in stackOverflow - What is a Factory Design Pattern in PHP?). The idea of factory classes is that objects are not mutable and merely serve the purpose of data container. I included PDO just for demonstration purposes but of course there are other ways (it just seems good for a simple users table)
class UserFactory
{
private $db;
public function __construct($db)
{
$this->db = $db;
}
public function fromID($id)
{
$userObject = new User();
$q = $this->db->prepare("SELECT * FROM user WHERE u_id = :id");
$q->bindValue(":id", $id);
$q->setFetchMode( PDO::FETCH_INTO, $userObject);
$q->execute();
$q->fetch(PDO::FETCH_INTO);
return $userObject;
}
public static function fromRow($row)
{
$userObject = new User();
$userObject->setName($row['name']);
$userObject->setEmail($row['name']);
return $userObject;
}
}
And as of collection of objects
class UserCollection
{
public static function getAllUsers($db)
{
$users = array();
$q = $db->query("SELECT * FROM user");
while($row = $q->fetch()){
$users[] = UserFactory::fromRow($row);
}
return $users;
}
}
The idea behind is to pass the DB connection to the static method that will return an array holding all User objects initialized from the database.
getAllUsers method here is static for demontration purposes and of course the same can be achieved by creating a contstructor that takes the database connection variable as an argument
Your first decision is whether or not to get the user's properties from the database within the class or to do it from outside the class. Lets say you do it outside the class, then you would not have any argument in the construct and you could have:
$users = array();
while($row = $result->fetch_assoc()) {
$user = new User();
for($row as $field => $value) {
$camelField = strtoupper(substr($field,0,1) . strtolower(substr($field, 1);
$fieldClass = 'set' . $camelField;
$user->{$fieldClass}($value);
}
$users[] = $user;
}
in your class you would have setters like
public function setName(value) {
$this-<name = $value;
}
There are mainly two approaches on how to persist your objects:
Active Record / Table Gateway
Using this approach, each property in a class is mapped to a certain field on a database table.
Since you're using PHP, you may be already used this pattern if you used Zend_Db or CodeIgniter Active Record.
The problems with this pattern are that it may not be suitable for complex domain where heavy inheritance is in-use and an in-depth mapping is required. also, it usually tightly-couple your classes with a database which may exacerbate testing.
See also: Wikipedia, Fowler
Object-Relational Mapper (ORM)
'ORM' is a much heavier solution and it let you work purely with 'objects' and completely abstracts away the table/database layer.
It also need to be able to handle Objects Inheritance, Composition, Polymorphism and usually provide some functionality for 'Lazy Loading' of referenced objects.
Notable 'ORM's for PHP are (for example): Doctrine and Propel.
See also: Wikipedia
Related
The title may be a little vague, but the question is difficult to word properly.
I'm trying to learn PHP OOP (coming from Procedural) and it's a pain - my main stump is selecting from a databased based on a certain value that is usually passed through the URL (at least in procedural).
For example, user.php?ID=2 - then I could quickly define ID using GET and future queries would use that ID.
Since my OOP classes would be in a seperate file to the main page that includes the html and outputs everything, users won't be submitting the ID to that file. In other words, they'll be going to user.php?ID=2 instead of user_c.php?ID=3 which is the class file.
My question is - how do I pass that ID through to the class? I need to select things out of the database based on the profile that they're viewing, but how do I tell the class that?
My apologies for how badly this is worded.
One would do something like this, $data now contains the data returned from the query:
//user_c.php:
Class MyUserClass {
public function getUser($id){
//Query for user data.
return $queryData;
}
}
//user.php
$userClass = new MyUserClass ();
$data = $userClass->getUser($_GET['ID']);
First of all, OOP is not that much different than procedural. The main difference is that instead of data and functions which operate on the data you have objects which encapsulate the data as well as the operations which are valid on that data.
However, in its core, OOP does encapsulate procedural programming, with the difference being that the procedural part happens within objects rather than in the application level.
To migrate from procedural to OOP all you need to do is separate your code in parts which are logically connected, in the case of databases what typically happens is each database table has a class (in MVC frameworks this is called a data model).
For example if you have a table called users you might have a corresponding User class.
class User {
private $id;
private $alsoOtherProperties;
public function __construct($dbconnection, $id) {
//Load the user from id
}
/* Setters and getters and other function here which operate on the user */
}
You then create an instance of a user which you construct from the $id given the database connection. The simplest way is do what you're already doing to get the id. From here on your data will be operating on the User object rather than on a database result. This way you don't have to worry about changing the database structure since you can just update the model to work with the new structure and the rest of the code will not need altering.
For example, say you want to update the "last logged in" column for a user at the time of log in:
//Other code around here
$ID = $db->real_escape_string(strip_tags(stripslashes($_GET['ID'])));
$user = new User($db,ID);
$user->setLastLogin(time());
$user->save();
In this example there's 2 functions defined in the class User in addition to the constructor which is to set the last login time and then update the database row which corresponds to the user. As you can see, this does not have any MySQL specific logic and the underlying code in the user class can update either a MySQL database, a text file, or not do anything (e.g. when just running tests).
Note: This is just an example, probably not a very good one at that, you should really really study OOP to learn more about it.
First and foremost you will need to create a simple database class that will handle your queries.
class DatabaseQuery {
public $parameters;
public $statement;
function __construct($statement,$parameters)
{
global $connection; //this will be your new PDO connection details
$sth = $mysqli->prepare($statement);
$sth ->execute($parameters);
$this -> executedStatement = $sth;
}
function getDetails()
{
$r_result = $this -> executedStatement;
$r_result2 = $r_result->fetch();
$show_result = $r_result2['0'];
return $show_result;
}
function executeStatementOnly()
{
return "Action Successful";
}
function __destruct()
{
//echo "Has been destroyed";
}
}
Next you will pick data from user, you will need to sanitize it using this function
function clean_data($data) {
$data = trim($data);
$data = stripslashes($data);
$data = htmlspecialchars($data);
return $data;
}
Next, pick the data and call your database query class and save or echo the data you are picking.
$get_data = clean_data($_GET["id"]);
$user_details = new DatabaseQuery("SELECT column FROM table WHERE id=?",array($get_data));
echo $user_details->getDetails();
Assuming that until now you did something like this:
// user.php
$id = $_GET['id'];
$myResult = myDbFunction($id);
function myDbFunction($id) {
// do something useful
}
you can re-write this like that:
// user_c.php:
Class MyClass {
public function myDbFunction($id) {
$something = "";
// do something useful
return $something;
}
}
// user.php:
include "user_c.php";
$myClass = new MyClass();
$id = $_GET['id'];
$myResult = $myClass->myDbFunction($id);
And that would produce the same results as if you had placed your class in the same file, like this:
// user.php:
Class MyClass {
public function myDbFunction($id) {
$something = "";
// do something useful
return $something;
}
}
$myClass = new MyClass();
$id = $_GET['id'];
$myResult = $myClass->myDbFunction($id);
I assume you know that one of the main reasons for going OOP over procedural is the re-usability as well as information hiding (i.e. sparing a user of your class the need to understand every detail of it, while still allowing them to use it)
You may want to read up on OOP with PHP, and simply play around with it. While there is a slight differece in the two styles, you should get a hang of it quickly.
Once you make sure you understood the single responsibility principle and follow it, you will surely find that OOP has many advantages over procedural programming.
I've recently learnt OOP in Java and I'm trying to implement what I've learned in my PHP usersystem.
This is my current User class
class User {
public $id;
public $session;
public $email;
public $lastVisit;
public function __construct($id) {
$conn = new Conn();
$array = $conn->ExecuteCmdArray("SELECT * FROM user WHERE id = '".$id."'");
$this->session = $array['session'];
$this->email = $array['email'];
$this->id = $array['id'];
$this->lastVisit = $array['last_visit'];
}
}
^ Oh, and am I supposed to execute a SQL to retrieve the data?
However, after taking a look at some examples online, I looked at their User class, but realised that in it, only functions like login etc. are present. The attributes in the class are also only the username and password.
Shouldn't it contain all the other variables e.g gender, real_name as well? It seems to me that the user class does not store the userdata, but it's only used for logging in and stuff.
Is this how a User class in PHP usually works - which means my User class is done wrongly?
Well there is no right way to design a User class. It depends on the programmers likes, needs, skills and his understanding of OOP and Software-Design.
Seperation of Concerns
Oh, and am I supposed to execute a SQL to retrieve the data?
It's not recommended. Good software design is about creating decoupled self-contained components.
When designing Software it's a good practice to think out of the box and put yourself into another developers shoes. So if you had a User object without knowing what's going behind the scenes. Would you expect it to fire Database-Queries? No it's not a Users responsibility to query the database.
OOP is also about reusability. If we take your example: If I threw your User class into my own project. It would likely break. You are instantiating a Database Connection directly in the class. What if I had other ways of handling DB access? Everything would break.
Seperation of Concerns is the keyword here. And you should adhere to it whenever it's possible.
However, after taking a look at some examples online, I looked at their User class, but realised that in it, only functions like login etc. are present.
Ask yourself these questions:
Should a User know how to log in? How his sessions are managed or is this the task of another service maybe?
Would you expect that a User can log itself in if you didn't know the class?
You see. By just thinking about the concerns of a class you can eliminate problems in design before they even occur.
I would not expect my User that he knows how to log in. I rather would expect a service of my application which is explicitly dedicated to that task, to handle it.
<?php
$authentication = new UserAuthenticationService();
$authentication->attemptLogin('username', 'password');
if( $authentication->check() )
{
$user = $authentication->getUser();
echo $user->username();
}
Build your applications so that your classes are as self-contained as possible and only have the dependencies they really need. It's one of the keys of successful software-design.
It's all about your domain
The attributes in the class are also only the username and password.
Shouldn't it contain all the other variables e.g gender, real_name as well? It seems to me that the user class does not store the userdata, but it's only used for logging in and stuff.
That depends on your use case. If you're creating an application where users can anonymously post stories of their last hangover then why would you need a real name there?
If you however are creating some enterprise-business-app-thingy you probably want to store that data. What data your objects hold is defined by you, and only by you.
Let's take our hangover-site a step further. I want only minimal information from my users so it could look like this.
<?php
class User {
private $username;
private $email;
private $gender;
public function __construct( $username )
{
$this->username = $username;
}
public function username()
{
return $this->username;
}
//[...]
public function setUsername( $username )
{
$this->username = $username;
}
//[...]
}
I don't even store the password on my User class because I don't want to. I decide that I will have some kind of persistance manager and an authentication manager which handle those.
<?php
$authentication = new UserAuthenticationService();
$persistanceMapper = new UserPersistanceMapper();
$authentication->attemptLogin('username', 'password');
if( $authentication->check() )
{
// Let's rename the User just for fun
$user = $authentication->getUser();
$user ->setName('Thomas');
$persistanceMapper->persist( $user );
}
It really depends on your likes. But what I wanted to show in the first place is, that I have objects that do only the thing(s) that they are responsible for, or supposed to do
The User is able to alter it's own state and is able to provide me with it's data. But he does not know anything about the database.
UserPersistanceMapper knows how to persist a User (in a database or wherever it's supposed to)
UserAuthenticationService knows how a users session needs to be handled
I don't have the one object that handles all of it. Instead we have self-contained objects here that are together handling our stuff.
It all comes down to your likes
Is this how a User class in PHP usually works - which means my User class is done wrongly?
Eventually there is no right and no wrong. If you want to roll that way, do it! You may gain an initial time boost if you are not thinking about design. That may be okay for simple projects that are not hard to maintain.
At the time you are building larger applications however, it's always good to reflect on your own code.
Keep in mind:
Try to put yourself into some other developers shoes while designing your application
Visualize how objects are connected to each other before you start coding
Try to keep your classes as self-contained as possible (pass eventual dependencies from the outside)
Get stuff done! If you can't come up with a clean way to do something: Just make it work. Refactor things later. But make sure you have a periodic refactoring cycle. Don't put stuff aside and think "Yeah... whatever I'll do this later". You will end up with a lot of Code Smells this way.
Further reading
Seperation of Concerns
PHP: The Right Way
SOLID Principles
The drawback with the way you made your user class is when you manage lists of users, or process things about lots of users at a time you have to move around all this extra user data, whereas sometimes you would only need it's id, and email.
We can use two or more classes! In your exemple there would be a minimal User class, with very minimal attributes and functions, and a Full_User class, extending the first one.
class User {
public $id;
public $email;
public function __construct($array) {
$this->email = $array['email'];
$this->id = $array['id'];
}
}
class Full_User {
public $session;
public $lastVisit;
public function __construct($array) {
$this->session = $array['session'];
$this->lastVisit = $array['last_visit'];
parent::__construct($array);
}
}
I'd suggest passing the array of properties to the constructor instead of executing the statement. It will allow creating objects from some other data then a database.
$id = 12;
$conn = new Conn();
$minimal_array = $conn->ExecuteCmdArray("SELECT id,mail FROM user WHERE id = '".$id."'");
$full_array = $conn->ExecuteCmdArray("SELECT id,mail,session,lastVisit FROM user WHERE id = '".$id."'");
$user_for_listing = new User($minimal_array);
$full_user = new Full_User($full_array);
Consider a Database interaction module written in PHP that contains classes for interacting with the database. I have not started coding the class so I won't be able to give code snippets.
There will be one class per database table as explained below.
User - A class for interacting with the user table. The class contains functions such as createUser, updateUser, etc.
Locations - A class for interacting with the locations table. The class contains functions such as searchLocation, createLocation, updateLocation, etc.
In addition, I am thinking of creating another class as follows: -
DatabaseHelper : A class that will have a member that represents the connection to the database. This class will contain the lower level methods for executing SQL queries such as executeQuery(query,parameters), executeUpdate(query,parameters) and so on.
At this point, I have two options to use the DatabaseHelper class in other classes : -
The User and Locations class will extend the DatabaseHelper class so that they can use the inherited executeQuery and executeUpdate methods in DatabaseHelper. In this case, DatabaseHelper will ensure that there is only one instance of the connection to the database at any given time.
The DatabaseHelper class will be injected in the User and Locations class through a Container class that will make User and Location instances. In this case, the Container will make sure that there is only one instance of DatabaseHelper in the application at any given time.
These are the two approaches that quickly come to my mind. I want to know which approach to go with. It is possible that both these approaches are not good enough, in which case, I want to know any other approach that I can go with to implement the database interaction module.
Edit:
Note that the Container class will contain a static member of type DatabaseHelper. It will contain a private static getDatabaseHelper() function that will return an existing DatabaseHelper instance or create a new DatabaseHelper instance if one does not exists in which case, it will populate the connection object in DatabaseHelper. The Container will also contain static methods called makeUser and makeLocation that will inject the DatabaseHelper into User and Locations respectively.
After reading a few answers, I realize that the initial question has almost been answered. But there is still a doubt that needs to be clarified before I can accept the final answer which is as follows.
What to do when I have multiple databases to connect to rather than a single database. How does the DatabaseHelper class incorporate this and how does the container inject appropriate database dependencies in the User and Location objects?
Lets answer your questions from top to bottom, and see what I can add to what you say.
There will be one class per database table as explained below.
User - A class for interacting with the user table. The class contains functions such as createUser, updateUser, etc.
Locations - A class for interacting with the locations table. The class contains functions >such as searchLocation, createLocation, updateLocation, etc.
Essentially you have to choices here. The method you described is called the active record pattern. The object itself knows how and where it is stored. For simple objects that interact with a database to create / read / update / delete, this pattern is really usefull.
If the database operations become more extensive and less simple to understand, it is often a good choice to go with a data mapper (eg. this implementation). This is a second object that handles all the database interactions, while the object itself (eg. User or Location) only handles operations that are specific to that object (eg. login or goToLocation). If you ever want to chance the storage of your objects, you will only have to create a new data mapper. Your object won't even know that something changed in the implementation. This enforces encapsulation and seperation of concerns.
There are other options, but these two are the most used ways to implement database interactions.
In addition, I am thinking of creating another class as follows: -
DatabaseHelper : A class that will have a static member that represents the connection to the database. This class will contain the lower level methods for executing SQL queries such as executeQuery(query,parameters), executeUpdate(query,parameters) and so on.
What you are describing here sounds like a singleton. Normally this isn't really a good design choice. Are you really, really certain that there will never be a second database? Probably not, so you should not confine yourself to an implementation that only allowes for one database connection. Instead of making a DatabaseHelper with static members, you can better create a Database object with some methods that allow you to connect, disconnect, execute a query, etc. This way you can reuse it if you ever need a second connection.
At this point, I have two options to use the DatabaseHelper class in other classes : -
The User and Locations class will extend the DatabaseHelper class so that they can use the inherited executeQuery and executeUpdate methods in DatabaseHelper. In this case, DatabaseHelper will ensure that there is only one instance of the connection to the database at any given time.
The DatabaseHelper class will be injected in the User and Locations class through a Container class that will make User and Location instances. In this case, the Container will make sure that there is only one instance of DatabaseHelper in the application at any given time.
These are the two approaches that quickly come to my mind. I want to know which approach to go with. It is possible that both these approaches are not good enough, in which case, I want to know any other approach that I can go with to implement the database interaction module.
The first option isn't really viable. If you read the description of inheritance, you will see that inheritance is normally used to create a subtype of an existing object. An User is not a subtype of a DatabaseHelper, nor is a location. A MysqlDatabase would be a subtype of a Database, or a Admin would be a subtype of an User. I would advise against this option, as it isn't following the best practices of object oriented programming.
The second option is better. If you choose to use the active record method, you should indeed inject the Database into the User and Location objects. This should of course be done by some third object that handles all these kind of interactions. You will probably want to take a look at dependency injection and inversion of control.
Otherwise, if you choose the data mapper method, you should inject the Database into the data mapper. This way it is still possible to use several databases, while seperating all your concerns.
For more information about the active record pattern and the data mapper pattern, I would advise you to get the Patterns of Enterprise Application Architecture book of Martin Fowler. It is full of these kind of patterns and much, much more!
I hope this helps (and sorry if there are some really bad English sentences in there, I'm not a native speaker!).
== EDIT ==
Using the active record pattern of data mapper pattern also helps in testing your code (like Aurel said). If you seperate all peaces of code to do just one thing, it will be easier to check that it is really doing this one thing. By using PHPUnit (or some other testing framework) to check that your code is properly working, you can be pretty sure that no bugs will be present in each of your code units. If you mix up the concerns (like when you choose option 1 of your choices), this will be a whole lot harder. Things get pretty mixed up, and you will soon get a big bunch of spaghetti code.
== EDIT2 ==
An example of the active record pattern (that is pretty lazy, and not really active):
class Controller {
public function main() {
$database = new Database('host', 'username', 'password');
$database->selectDatabase('database');
$user = new User($database);
$user->name = 'Test';
$user->insert();
$otherUser = new User($database, 5);
$otherUser->delete();
}
}
class Database {
protected $connection = null;
public function __construct($host, $username, $password) {
// Connect to database and set $this->connection
}
public function selectDatabase($database) {
// Set the database on the current connection
}
public function execute($query) {
// Execute the given query
}
}
class User {
protected $database = null;
protected $id = 0;
protected $name = '';
// Add database on creation and get the user with the given id
public function __construct($database, $id = 0) {
$this->database = $database;
if ($id != 0) {
$this->load($id);
}
}
// Get the user with the given ID
public function load($id) {
$sql = 'SELECT * FROM users WHERE id = ' . $this->database->escape($id);
$result = $this->database->execute($sql);
$this->id = $result['id'];
$this->name = $result['name'];
}
// Insert this user into the database
public function insert() {
$sql = 'INSERT INTO users (name) VALUES ("' . $this->database->escape($this->name) . '")';
$this->database->execute($sql);
}
// Update this user
public function update() {
$sql = 'UPDATE users SET name = "' . $this->database->escape($this->name) . '" WHERE id = ' . $this->database->escape($this->id);
$this->database->execute($sql);
}
// Delete this user
public function delete() {
$sql = 'DELETE FROM users WHERE id = ' . $this->database->escape($this->id);
$this->database->execute($sql);
}
// Other method of this user
public function login() {}
public function logout() {}
}
And an example of the data mapper pattern:
class Controller {
public function main() {
$database = new Database('host', 'username', 'password');
$database->selectDatabase('database');
$userMapper = new UserMapper($database);
$user = $userMapper->get(0);
$user->name = 'Test';
$userMapper->insert($user);
$otherUser = UserMapper(5);
$userMapper->delete($otherUser);
}
}
class Database {
protected $connection = null;
public function __construct($host, $username, $password) {
// Connect to database and set $this->connection
}
public function selectDatabase($database) {
// Set the database on the current connection
}
public function execute($query) {
// Execute the given query
}
}
class UserMapper {
protected $database = null;
// Add database on creation
public function __construct($database) {
$this->database = $database;
}
// Get the user with the given ID
public function get($id) {
$user = new User();
if ($id != 0) {
$sql = 'SELECT * FROM users WHERE id = ' . $this->database->escape($id);
$result = $this->database->execute($sql);
$user->id = $result['id'];
$user->name = $result['name'];
}
return $user;
}
// Insert the given user
public function insert($user) {
$sql = 'INSERT INTO users (name) VALUES ("' . $this->database->escape($user->name) . '")';
$this->database->execute($sql);
}
// Update the given user
public function update($user) {
$sql = 'UPDATE users SET name = "' . $this->database->escape($user->name) . '" WHERE id = ' . $this->database->escape($user->id);
$this->database->execute($sql);
}
// Delete the given user
public function delete($user) {
$sql = 'DELETE FROM users WHERE id = ' . $this->database->escape($user->id);
$this->database->execute($sql);
}
}
class User {
public $id = 0;
public $name = '';
// Other method of this user
public function login() {}
public function logout() {}
}
== EDIT 3: after edit by bot ==
Note that the Container class will contain a static member of type DatabaseHelper. It will contain a private static getDatabaseHelper() function that will return an existing DatabaseHelper instance or create a new DatabaseHelper instance if one does not exists in which case, it will populate the connection object in DatabaseHelper. The Container will also contain static methods called makeUser and makeLocation that will inject the DatabaseHelper into User and Locations respectively.
After reading a few answers, I realize that the initial question has almost been answered. But there is still a doubt that needs to be clarified before I can accept the final answer which is as follows.
What to do when I have multiple databases to connect to rather than a single database. How does the DatabaseHelper class incorporate this and how does the container inject appropriate database dependencies in the User and Location objects?
I think there is no need for any static property, nor does the Container need those makeUser of makeLocation methods. Lets assume that you have some entry point of your application, in which you create a class that will control all flow in your application. You seem to call it a container, I prefer to call it a controller. After all, it controls what happens in your application.
$controller = new Controller();
The controller will have to know what database it has to load, and if there is one single database or multiple ones. For example, one database contains the user data, anonther database contains the location data. If the active record User from above and a similar Location class are given, then the controller might look as follows:
class Controller {
protected $databases = array();
public function __construct() {
$this->database['first_db'] = new Database('first_host', 'first_username', 'first_password');
$this->database['first_db']->selectDatabase('first_database');
$this->database['second_db'] = new Database('second_host', 'second_username', 'second_password');
$this->database['second_db']->selectDatabase('second_database');
}
public function showUserAndLocation() {
$user = new User($this->databases['first_database'], 3);
$location = $user->getLocation($this->databases['second_database']);
echo 'User ' . $user->name . ' is at location ' . $location->name;
}
public function showLocation() {
$location = new Location($this->database['second_database'], 5);
echo 'The location ' . $location->name . ' is ' . $location->description;
}
}
Probably it would be good to move all the echo's to a View class or something. If you have multiple controller classes, it might pay off to have a different entrypoint that creates all databases and pushes them in the controller. You could for example call this a front controller or an entry controller.
Does this answer you open questions?
I would go with the dependancy injection, for the following reason: if at some point you want to write tests for your applications, it will allow you to replace the DatabaseHelper instance by a stub class, implementing the same interface but that do not really access a database. This will make it really easier to test your model functionalities.
By the way, for this to be really useful, your other classes (User, Locations) should depend on a DatabaseHelperInterface rather than directly on DatabaseHelper. (This is required to be able to switch implementations)
The question of Dependency Injection vs. Inheritance, at least in your specific example comes down to the following: "is a" or "has a".
Is class foo a type of class bar? Is it a bar? If so, maybe inheritance is the way to go.
Does class foo use an object of class bar? You're now in dependency injection territory.
In your case, your data access objects (in my code approach these are UserDAO and LocationDAO) are NOT types of database helpers. You would not use a UserDAO, for instance, to provide database access to another DAO class. Instead, you USE the features of a database helper in your DAO classes. Now, this doesn't mean that technically you could not achieve what you want to do by extending the database helper classes. But I think it would be a bad design, and would cause trouble down the road as your design evolves.
Another way to think about it is, is ALL of your data going to come from the database? What if, somewhere down the road, you want to pull some location data from, say, an RSS feed. You have your LocationDAO essentially defining your interface -- your "contract", so to speak -- as to how the rest of your application obtains location data. But if you had extended DatabaseHelper to implement your LocationDAO, you'd now be stuck. There'd be no way to have your LocationDAO use a different data source. If, however, DatabaseHelper and your RSSHelper both had a common interface, you could plug the RSSHelper right into your DAO and LocationDAO doesn't even have to change at all. *
If you had made LocationDAO a type of DatabaseHandler, changing the data source would require changing the type of LocationDAO. This means that not only does LocationDAO have to change, but all your code that uses LocationDAO has to change. If you had injected a datasource into your DAO classes from the start, then the LocationDAO interface would remain the same, regardless of the datasource.
(* Just a theoretical example. There'd be a lot more work to get a DatabaseHelper and RSSHelper to have a similar interface.)
What you are describing with your User and Location classes is called a Table Data Gateway:
An object that acts as a Gateway to a database table. One instance handles all the rows in the table.
In general, you want to favor Composition over Inheritance and programm towards an interface. While it may seem like more effort to assemble your objects, doing it will benefit maintenance and the ability to change the program in the long run (and we all know change is the only ever constant in a project).
The most obvious benefit of using Dependency Injection here is when you want to unit test the Gateways. You cannot easily mock away the connection to the database when using inheritance. This means you will always have to have a database connection for these tests. Using Depedency Injection allows you to mock that connection and just test the Gateways interact correctly with the Database Helper.
Even though the other answers here are very good, I wanted to throw in some other thoughts from my experiences using CakePHP (an MVC framework). Basically, I will just show you a leaf or two out of their API; mainly because - to me - it seems well defined and thought out (probably because I use it daily).
class DATABASE_CONFIG { // define various database connection details here (default/test/externalapi/etc) }
// Data access layer
class DataSource extends Object { // base for all places where data comes from (DB/CSV/SOAP/etc) }
// - Database
class DboSource extends DataSource { // base for all DB-specific datasources (find/count/query/etc) }
class Mysql extends DboSource { // MySQL DB-specific datasource }
// - Web service
class SoapSource extends DataSource { // web services, etc don't extend DboSource }
class AcmeApi extends SoapSource { // some non-standard SOAP API to wrestle with, etc }
// Business logic layer
class Model extends Object { // inject a datasource (definitions are in DATABASE_CONFIG) }
// - Your models
class User extends Model { // createUser, updateUser (can influence datasource injected above) }
class Location extends Model { // searchLocation, createLocation, updateLocation (same as above) }
// Flow control layer
class Controller extends Object { // web browser controls: render view, redirect, error404, etc }
// - Your controllers
class UsersController extends Controller { // inject the User model here, implement CRUD, this is where your URLs map to (eg. /users/view/123) }
class LocationsController extends Controller { // more CRUD, eg. $this->Location->search() }
// Presentation layer
class View extends Object { // load php template, insert data, wrap in design }
// - Non-HTML output
class XmlView extends View { // expose data as XML }
class JsonView extends View { // expose data as JSON }
Dependency Injection is preferred if you have different types of services, and one service want to use other.
Your classes User and Locations sounds more like DAO (DataAccessObject) layer, that interact with database, So for your given case you should be using In Inheritance. Inheritance can be done by extending class or implementing Interfaces
public interface DatabaseHelperInterface {
public executeQuery(....);
}
public class DatabaseHelperImpl implemnets DatabaseHelperInterface {
public executeQuery(....) {
//some code
}
public Class UserDaoInterface extends DatabaseHelperInterface {
public createUser(....);
}
public Class UserDaoImpl extends DatabaseHelperImpl {
public createUser(....) {
executeQuery(create user query);
}
In this way your database design and code will be separate.
I've just started using OOP PHP and ran into a question. I've set up a generic mysql class that allows me to connect to a database and has some functions to obtain records from a table:
class mysql{
//some lines to connect, followed by:
public function get_record($sql)
{
$result = mysql_result(mysql_query($sql));
return $result;
//obiously it's a bit more advanced, but you get the picture.
}
}
Next, I have a class to obtain user details:
class user{
__construct($id)
{
$this->id = $id
}
public function get_username($id)
{
$username = get_record("SELECT name FROM users WHERE id = '".$this->id."'");
return $username;
}
}
I tried this, but got the error that the function get_record was unkown. I solved this by adding $mysql = new mysql(); to the user class.
However, it feels quite inefficient to have to instantiate the mysql object for every class that uses my database methods (that's pretty much all of them).
Is there a way to make the mysql class and its methods accessible to all other classes, without having to call the mysql class in every method?
For one, you don't need to use singleton in this case - or actually, you almost never do. See this article, for example.
Second, I think your OO designs are a bit off. The main point of object-oriented programming and design is to isolate responsibility into separate classes. Right now, you're giving your User class two main responsibilities - store / carry one user's relevant data, and query the data service (in this case, a simple MySQL / database abstraction layer).
You should first move that functionality into a separate object. Usually, this is called a Service - so in this case, it's a UserService. A UserService has one responsibility: provide access to User objects. So it'd sorta look like this:
class UserService {
public function __construct($mysql); // uses the mysql object to access the db.
public function get($id) {
$result = $this->mysql->get_record("select x from y");
$user = new User($result['id'], $result['name']); // assuming user has a constructor that takes an id and a name
return $user;
}
public function save($user);
public function delete($user);
}
You tie it all together at the start of your request (or where you need to access users):
$mysql = new MySQL($credentials);
$service = new UserService($mysql);
$user = $service->find(1337);
It's not perfect, but it's a much neater design. Your MySQL object does what it needs to do (build a connection, execute queries), your user object is plain dumb, and your service does only one thing, i.e. provide a layer between the actual storage layer and the thing calling it.
Design your mysql class to be called statically:
$username = Mysql::get_record("SELECT name FROM users WHERE id = '".$this->id."'");
http://php.net/manual/en/language.oop5.static.php
This is a common problem, and so there is a common solution to this.
As you might know, in software development common solutions on common problems are called Design Patterns.
There are two design patterns that can help you solve this problem.
In a more abstract sense the problem you are facing is:
How can i make class A available in class B?
The Singleton pattern
"In the singleton pattern a class can distribute one instance of itself to other classes."
This is not exactly what you are looking for, as your website may use multiple database connections. However, it is used by a lot of people in this way.
Read some information about using a singleton class as a database provider here:
https://www.ibm.com/developerworks/library/os-php-designptrns/#N10124
More information on the singleton pattern in PHP:
http://www.fluffycat.com/PHP-Design-Patterns/Singleton/
Another sensible approach is the registry pattern:
Registry Pattern
You can find information about the registry pattern on the link below, as well as an implementation almost identical that you are looking for:
http://www.sitecrafting.com/blog/php-patterns-part/
Even more powerful is a combination between the singleton and the registry.
Good luck and enjoy learning OOP PHP!
You should pass in the mysql object to each user object. So it would look like this:
$mysql = new mysql();
$user = new user( $mysql, $id);
$name = $user->get_username();
class user {
public function __construct($mysql, $id) {
$this->mysql = $mysql;
$this->id = $id;
}
public function get_username() {
$username = $this->mysql->get_record("SELECT name FROM users WHERE id = '".$this->id."'");
return $username;
}
}
using global variables, although that is probably not the best option.
$mysql = new mysql();
function someFunction() {
global $mysql;
$mysql->get_record(...)
}
or a static method for your mysql class (see Singleton)
class mysql {
public static $theInstance = new mysql();
public static function getInstance() {
return $this->theInstance;
}
}
function someFunction() {
$database= mysql::getInstance();
$database->get_record(...)
}
Start to think to use Doctrine, it's better
http://www.doctrine-project.org/
Alright, I'm working on making a Member class for my website. I want to make it as optimized as possible. Currently, the constructor can take ($resource) either an int (to grab info from one member in the database, based on id) or an array of ints (to grab multiple members from the database, and store them in an array member variable).
I would like to know if there are any inprovements I can make with my block of code below, before I move on to creating more parts of my website. What could be changed to make it better? Is there a better layout I should follow for doing this kind of thing?
public function __construct($resource) {
global $database;
if (is_string($resource) || is_int($resource)) {
$resource = (int)$resource;
$query = $database->query("SELECT * FROM members WHERE member_id = {$resource} LIMIT 1");
$row = $database->get_row($query);
foreach ($row as $key => $value) {
$this->field[$key] = $value;
}
} else if (is_array($resource)) {
$query = $database->query("SELECT * FROM members WHERE member_id IN(" . implode(",",$resource) . ")");
while ($member = $database->get_row($query)) {
$this->member_list[$member['member_id']] = $member;
}
}
}
Some thoughts:
Globals are bad
Database calls should be isolated to a data access layer, ideally of the ORM variety so that you aren't writing manual SQL.
What if $resource is "ddd", do you want the member with a member_id of 1 ?
You aren't protecting against SQL injection.
Shouldn't your member_list be creating new Member objects (or whatever this class is called) rather than simply appending the row data?
Firstly, don't do work in a constructor. Secondly, there are many packages out there that do exactly what you're trying to do, and do it VERY well.
What you're trying to write is called a Model. It's a class that mirrors a table in the database. Use a mature ORM (Object Relational Mapper) package such as Propel or Doctrine for automatically generating classes based off of database schemas. I personally recommend Propel over Doctrine (though they are both great packages).
Also, I'd recommend that you use the symfony php framework, which integrates Propel as its ORM (again, you can use Doctrine as an alternative ORM with Symfony).
Lastly, don't use globals. Write a class around any resource that access. Making a static call to retrieve its singleton instance such as Database::getInstance() is a much preferred way of accessing the database (or any other) resource.
Best of luck