So I know that questions with 'what is the best' in their title aren't supposed to be asked, but really.. how should you do this?
We have a database class and, for example, a user class. A user class will get methods such as create() and update(), which will need to do database stuff.
As far as I know there are 2 main options, passing on the database object in every __construct() or make the database class static.
(Any other tips about OOP + database driven websites are also appreciated)
A very common pattern here is to make the database class a singleton construct, which is then passed to every object constructor (that is called Dependency Injection).
The purpose of making the database object a singleton is to ensure that only one connection is made per page load. If you need multiple connections for some reason, you would want to do it a different way. It's important to pass it via the constructors though, rather than creating the database object inside an unrelated class so that you can more easily test and debug your code.
// Basic singleton pattern for DB class
class DB
{
// Connection is a static property
private static $connection;
// Constructor is a private method so the class can't be directly instantiated with `new`
private function __construct() {}
// A private connect() method connects to your database and returns the connection object/resource
private static function connect() {
// use PDO, or MySQLi
$conn = new mysqli(...);
// Error checking, etc
return $conn;
}
// Static method retrieves existing connection or creates a new one if it doesn't exist
// via the connect() method
public static function get_connection() {
if (!self::$connection) {
self::$connection = self::connect();
// This could even call new mysqli() or new PDO() directly and skip the connect() method
// self::$connection = new mysqli(...);
}
return self::$connection;
}
}
class Other_Class
{
// accepts a DB in constructor
public function __construct($database) {
//stuff
}
}
// Database is created by calling the static method get_connetion()
$db = DB::get_connection();
$otherclass = new Other_Class($db);
// Later, to retrieve the connection again, if you don't use the variable $db
// calling DB::get_connection() returns the same connection as before since it already exists
$otherclass2 = new Other_Class(DB::get_connection());
Another method is to create your database class directly extending either mysqli or PDO. In that case, the __construct() method supplies the object to getConnect(), as in
public static function get_connection() {
if (!self::$connection) {
self::$connection = new self(/* params to constructor */);
}
return self::$connection;
}
Well, what you can do is to have the database access layer in one object, which is then passed to your objects, respecting the inversion of control pattern.
If you want to dig a bit into this direction, have a look into dependency injection (DI): http://en.wikipedia.org/wiki/Dependency_injection
Having a singleton is usually a bad idea as you will end up having problems when testing your code.
Having the database access logic within a model class such as User violates the separation of concerns principle. Usually DAO (Data Access Object) handles db related concerns.
There are ORM frameworks such as Hibernate, which handle mismatch between OO and relational models quite well, potentially saving a lot of manual work.
I'm really surprised that no one said this, but here it goes: ORM.
If your weapon of choice is PHP, then the major options are Propel and Doctrine. They both have many strengths and some weaknesses, but there's no doubt that they're powerfull. Just an example, from Propel's (my personal favourite) user manual:
// retrieve a record from a database
$book = BookQuery::create()->findPK(123);
// modify. Don't worry about escaping
$book->setName('Don\'t be Hax0red!');
// persist the modification to the database
$book->save();
$books = BookQuery::create() // retrieve all books...
->filterByPublishYear(2009) // ... published in 2009
->orderByTitle() // ... ordered by title
->joinWith('Book.Author') // ... with their author
->find();
foreach($books as $book) {
echo $book->getAuthor()->getFullName();
}
You won't get more OO than that!
They will handle a lot of things for you like for one, abstracting your data from the database vendor. That said, you should be able to move (relatively painlessly) from MySQL to SQL Server and if you're building your own tools for web applications, then beign able to adapt to different environments is a very important thing.
Hope I can help!
Hey have a look at ORM's. Let them do the hard work for you? fluent nhibernate or microsofts entity framework.
I could be misunderstanding your question. Sorry if so
Related
I am currently working in PHP and have begun to utilise classes- I am learning a lot, however I am yet to have my "penny drop" moment- I am struggling with object interaction.
I'd really appreciate some clarification in regards to how one object should interact with another. As a very basic example if I have a database object which handles connecting and querying a database, how should other classes access the results of queries performed by the database object?
From my understanding so far, I can see 2 options. Either the query results within the database class are accessible publicly and are passed to other objects as arguments...
$databaseObject = new DatabaseObject;
$databaseObject->query("query goes here");
$newObject = randomObject;
$newObject->doStuff($databaseObject->query())
Or objects which rely on query results instantiate new database objects within themselves and therefore the results are contained within that object.
class databaseConnection {
public $queryResults;
function __construct {
connect to database...
}
function query {
perform queries...
$this->queryResults = query results
}
}
class NewObject
{
function doStuff() {
$db = new databaseConnection
do stuff with $db->queryResults
}
}
Option 1 seems wrong as properties in the database class are available globally, whereas option 2 seems to contradict the idea that classes should only hold methods and properties relating to the object they define.
I could think of many other examples. If I create a class responsible for managing a user throughout a system, yet classes responsible for other tasks need to know what privilege level a user has, do I make that property within the user class global and pass it to other classes? Do the other classes instantiate new user objects?
Any help much appreciated.
Either the query results within the database class are accessible publicly
This (for me) is the key to the answer. If you set or change a value in the instance, this rather implies that you want to set the value in the underlying dataset (although you might consider defering the write). Note that the magic methods allow you to associate actions with get and set operations implicitly. But not every query is updateable. If your sql is baked in, then you can determine the updatability at design time.
Also, I suggest that your query object has a set of record objects associated with it where you interact with the underlying data. Bundling the connection functionality in the same object as the query only really makes sense if it is a factory (supporting multiple queries) and creating query result objects. And the query (result) object should probably implement the iterator interface.
Both pdo and mysqli seperate the connection, query and results into seperate objects - for good reason.
class Connection {
public static $conn;
public static function getInstance() {
if (!self::$conn) {
self::$conn = new Connection();
}
return self::$conn;
}
public function query() {
echo "run your query here using self::\$conn object";
}
}
class Person {
public function doStuff() {
$conn = Connection::getInstance();
$results = $conn->query();
}
}
$person = new Person();
$person->doStuff();
Firstly, you want to get your database connection only one time rather then opening it every time.
Secondly, using the same database connection object you can run multiple queries as shown in the above example.
You will always get a single connection no matter how many other classes you use.
In PHP, I have two classes: Database and Item.
Database contains the connection properties and methods. For example, Database::Query can be used to pass a query string, etc.
Item is a generic item identifier. It's built by passing it an itemID which is then used to query the database for the rest of the item information.
In this case, what's the best practice for creating Item objects if they require database access? Is it normal to create each one using this syntax:
$item = new Item(12345, $db);
Or is it better, acceptible, or possible to create the Database object and have it used for each Item created in the application, such that the call could become:
$item = new Item(12345);
The second seems a lot cleaner (and can be expanded so that similar types of objects don't also need that $db addon), but I'm looking for suggestions from those who have more experience at this than I do! Thanks!
I would suggest that most seasoned developers would lean toward the approach of dependency injection as demonstrated in your first example.
Why?
Well largely because this allows you to decouple the class to which the dependency is being injected from the dependency's implementation.
So consider this dependency injection example:
Class some_class {
protected $db;
__construct($db) {
if($db instanceof some_db_class === false) {
throw new Exception('Improper parameter passed.');
}
$this->db = $db;
}
}
Here you could pass any type of object so long as it was an instance of some_db_class it could be a subclass of that object that implements the same methods used by this class. That doesn't matter to this class as long as the methods are implemented (you of course could also check that a passed object implements a specific interface in addition to or in lieu of checking its instance type).
This means that, for example, you can pass a mock DB object for testing or something like that. The class doesn't care as long as the methods are implemented.
Now consider the singleton approach (or similar instantiation of DB from with the class):
Class some_class {
protected $db;
__construct() {
$this->db = some_db_class::get_instance();
}
}
Here you have tightly coupled your class to a specific database class. If you wanted to test this class with a mock DB implementation it becomes very painful in that you need to modify the class to do so.
I won't even get into discussion of using global as that is just poor practice and should not be considered at all.
I would recommend using the Singleton Pattern for your database connection. This is actually the best practice. As you really dont need to instances of your database connection.
class Database_Instance
{
private static $database;
public static function getDatabaseObject() {
if (!self::$db) {
self::$db = new PDO( );
}
return self::$db;
}
}
function callWhatSoEver()
{
$connection = Database_Instance::getDatabaseObject();
}
For more information about the singleton pattern, see: http://en.wikipedia.org/wiki/Singleton_pattern
Typically a database connection object is global, or accessible globally. That works well for the vast majority of applications.
I do something like this (simplified for example purposes):
$db = connect_to_db();
function GetDB()
{
global $db;
return $db
}
//inside the item object
function Load( $id)
{
$db = GetDB();
$db->query(..);
}
There are, of course, cases where this isn't the best route. As always, it depend on the specific needs of your application.
I am not sure if this is totally the wrong thing to do, so I am looking for a bit of advice.
I have set up a database class with the constructor establishing a PDO connection to a MySQL database.
I've been looking at singletons and global variables, but there always seems to be someone who recommends against either/or.
I'm experimenting with a user class which extends the database class, so I can call upon the PDO functions/methods but maintain separate user class code. Is this a stupid thing to do?
You should generally pass a connection into your user, so your user class would take a database type object into its constructor and then use that database object to execute queries against the database. That way your data access logic remains separate from your business logic. This is called composition, as opposed to what you're talking about, which is inhertance.
If you really wanted to be technical, it would be best to have a user object with nothing but public variables, and then you would use a 'service' to implement your business logic.
class UserService implements IUserService
{
private $_db;
function __construct(IDb $db) {
$this->_db = db;
}
function GetAllUsers() {
$users = Array();
$result = $this->_db->Query("select * from user")
foreach($result as $user) {
//Would resolve this into your user domain object here
users[] = $user;
}
return users;
}
}
Well, ask yourself if User is a special case of Database. I'm not sure how others perceive it, but I would be kind of offended. I think what you need is to read about the Liskov substitution principle.
As for solving your "people tell me that globals are bad" issue, here are two videos you should watch:
The Clean Code Talks - Don't Look For Things!
The Clean Code Talks - Global State and Singletons
The idea behind class extensions in OOP is for child classes to be related to the parent classes. For instance, a school might have a Person class with extension classes of Faculty and Students. Both of the child classes are people, so it makes sense for them to extend the Person class. But a User is not a type of Database, so some people might get upset if you make it an extension.
Personally, I would send the database object as an argument to the User class in the constructor and simply assign that object to a class property. For instance:
class User
{
protected $db;
function __construct($username, $password, $db)
{
//some code...
$this->db = $db;
}
}
Alternatively, though some might yell at you for it, you can use the global keyword to inherit a variable in the global scope for use within your methods. The downside is that you would then have to declare it global in every method that needs it, or you could do:
class User
{
protected $db;
function __construct($username, $password)
{
global $db;
//some code...
$this->db = $db;
}
}
But in answer to your question, no I don't think you should make User an extension of Database; even though it would do what you need, it isn't a proper OOP practice.
It is pretty simple according to the definition of an object. It is the encapsulation of data and the operation which is performed on that data so if we only consider the theoretical point of view it would leads us in pleasurable environment.
My suggestion would be to create an abstract data access class with the generalized basic crud operations and a simple query execution using either PDO, ADO or some other database abstraction library. Now use this class as a parent for most of your model classes like the User.
Now the basic CRUD is provided by the abstract data access class and you can write the behavior specific to the user object like getting all posts for the user by consuming the simple query interface of the abstract parent class.
This approach will bring more modularity in term of coupling functionality and more readability and reuse-ability.
I don't see anything wrong with it for specific cases. You could use it for something as simple as wrapping a user's DB credentials in an object so they don't have to specify them everywhere the DB object is used.
$db = new UserDB();
would be a bit nicer than
$db = new StandarDB($username, $password, $default_db);
I have one database wrapper class. How should I use this class object to execute query in other class?
$liveresellerdb=new Database('host','user','spswd','db');
$fetch = $liveresellerdb->getResult($select_resellerData);
How should I include the database object in my one class?
Class one
{
function a (){
$sql="select * from table ";
//how should i execute here my query i mean to say
//every time i can't create the new object
// i want to know the good method by which i just execute the query by
// giving the database name
}
}
I'd advise against the Singleton pattern (using static members is a variation of this pattern) and use Dependency Injection instead. This means that you pass the database object to your service (the class that uses the connection) through the constructor.
Here is an example.
class UserFinder
{
private $db;
public function __construct(Database $db)
{
$this->db = $db;
}
public function findAllActive()
{
$sql = 'SELECT * FROM users WHERE active = 1';
return $this->db->executeAndFetchAll($sql);
}
}
$db = new Database($host, ...);
$finder = new UserFinder($db);
$users = $finder->findAllActive();
This ensures that you are not bound to a specific implementation of the Database class (you could make a sub-class) and will allow you to create separate UserFinders with separate Database instances. It will also make it easier to write tests for your application because you have less dependencies, which are not hidden and also replaceable.
In short: Use dependency injection.
Since global variables are dirty (you always need the global $var; statement), the easiest solution is to store them in a static member of a class, e.g. Database::$db.
Another solution (in a proper OOP environment) would be passing the database instance to the classes - in your code it would be the constructor of one which accepted the instance and then stored in a private member variable.
Maybe, you should think about implementing your Database class according to a Singleton Pattern.
Updated (according to comment below):
Ok. I have only one suggestion here (except passing object via method's parameters and Dependency Injection, described in igorw's comment)...
Dependency Injection is a good way, but this case you - I suppose - have some small amount of databases, so it can be better to save them all in some static private array and get by keys.
So you will have only one public static method getInstance($key) and keys can be stored as some predefined constants (to avoid "spelling" errors).
This way you don't require initialization at all (getInstance($key) can create new Database objects with necessary parameters [passed to constructor] depending on the $key parameter). Dependency Injection looks better in general, but in some particular cases this way can be easier-to-use.
Could be ok to have a Db setAdapter method that store database connections in a static property by name:
Db::setAdapter('db1', 'mysql:host=localhost;dbname=' . $dbname, $user, $pass);
Db::setAdapter('db2', 'mysql:host=localhost;dbname=' . $dbname2, $user2, $pass2);
Then a getAdapter method that will return a database connection when needed:
Db::getAdapter(); // return the default one
Db::getAdapter('db2'); // return an instance by its name
Behind the scenes you could implement a lazy connection too.
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/