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'm in the process of re factoring a lot of code to make it more testable and I have a bunch of useful functions that rely on an instantiated database object.
Things like this:
function id_from_name($table, $name)
{
$db = get_database();
//code that returns an id
}
function username_from_user_id($id)
{
$db = get_database();
//code that returns a username
}
There are a bunch more like id_exists, id_active etc.
Now I'm thinking that this isn't the right thing to do as the object should probably be passed through as an argument? But then that means creating and sending in a new object into each of these functions every time i want to use one.
So really, my questions are: Should I be moving these functions into their own class/library that has access to the database object? and are the examples that I've shown above generally a bad way of doing things?
A better approach would be indeed to make classes. And you would be passing the database object to the constructor and make it an instance variable. That way every function would have access to the database object.
Now the reason why it is considered bad to instantiate e.g. your database object in every function, is because if you decide for example one day to change your datasource, you might need a huge refactor. If you pass your database object into the constructor, you can just pass/inject the right object into the class without any refactor.
...a bit more about DI below...
By passing your objects into the constructors, you also create a more clear API => you know which object depends on the other, you know exactly which class uses your DB object. If you start instantiating it or accessing it in a static way inside the functions like you did, I would have to look through all your classes to see where your DB object is used. One more point, dependency injection forces SRP (single responsibility principle) => if you start injecting too many objects (constructor gets many arguments), you should suspect your class is doing too much than what it should, and start refactoring.
You can create a class Table_Adapter and instantiate database object inside its constructor:
class Table_Adapter
{
protected $db;
public function __construct()
{
$db = get_database();
}
}
Then you create a child class Items_Table_Adapter' that extendsTable_Adapterand put their all methods related toItems` table.
class Items_Table_Adapter extends Table_Adapter
{
public function item_by_id($id)
{
}
}
Then you use it like:
$tableAdapter = new Items_Table_Adapter();
$item = $tableAdapter->item_by_id(1);
Try something like:
class YourClass{
public static function get_database(){
// your creation
return $db;
}
public function id_from_name($table, $name)
{
/* your code */
//code that returns an id
}
public function username_from_user_id($id)
{
/* your code */
}
}
so you could just use it this way:
$db = YourClass::get_database();
$result = $db->id_from_name($table, $name);
It is certainly recommended that you have the option to swap out your database connection.
Now, if your function get_database() looks like this:
function get_database() {
static $db;
if (!$db)
$db = new \mysqli(...);
return $db;
}
Then you really, really should change it to a wrapper around a class, looking like this:
function get_database_manager() {
static $dbmgr;
if (!$dbmgr)
$dbmgr = new DbManager;
return $dbmgr;
}
function get_database() {
return get_database_manager()->getCurrentConnection();
}
where DbManager has an instance attribute with the current connection that is returned with getCurrentConnection(). If you want to swapt out the connection, do something like get_database_manager()->setConnection($newConn). Problem solved :)
I'll leave the downsides of static programming here (it remains with many examples in this thread): http://kunststube.net/static/
as well as the common method to get rid of that (we have another approach here): http://en.wikipedia.org/wiki/Dependency_injection
I've a simple application, say it has some classes and an "extra" one that handles database requests. Currently i'm creating the database object everytime the app is used, but in some cases there's no need for a database connection. I'm doing it like this (PHP btw):
$db = new Database();
$foo = new Foo($db); // passing the db
But sometimes the $foo object does not need db access, as only methods without database actions are called. So my question is: What's the professional way to handle situations like this / how to create the db connection/object only when needed ?
My goal is to avoid unnecessary database connections.
Note: Although the direct answer to ops question, "when can I only create / connect to the database when required and not on every request" is inject it when you need it, simply saying that is not helpful. I'm explaining here how you actually go about that correctly, as there really isn't a lot of useful information out there in a non-specific-framework context to help in this regard.
Updated: The 'old' answer to this question can be see below. This encouraged the service locator pattern which is very controversial and to many an 'anti-pattern'. New answer added with what I've learned from researching. Please read the old answer first to see how this progressed.
New Answer
After using pimple for a while, I learned much about how it works, and how it's not actually that amazing after all. It's still pretty cool, but the reason it's only 80 lines of code is because it basically allows the creation of an array of closures. Pimple is used a lot as a service locator (because it's so limited in what it can actually do), and this is an "anti-pattern".
Firstly, what is a service locator?
The service locator pattern is a design pattern used in software development to encapsulate the processes involved in obtaining a service with a strong abstraction layer. This pattern uses a central registry known as the "service locator" which on request returns the information necessary to perform a certain task.
I was creating pimple in the bootstrap, defining dependencies, and then passing this container to each and every single class I instantiated.
Why is a service locator bad?
What's the problem with this you say? The main problem is that this approach hides dependencies from the class. So if a developer is coming to update this class and they haven't seen it before, they're going to see a container object containing an unknown amount of objects. Also, testing this class is going to be a bit of a nightmare.
Why did I do this originally? Because I thought that after the controller is where you start doing your dependency injection. This is wrong. You start it straight away at the controller level.
If this is how things work in my application:
Front Controller --> Bootstrap --> Router --> Controller/Method --> Model [Services|Domain Objects|Mappers] --> Controller --> View --> Template
...then the dependency injection container should start working right away at the first controller level.
So really, if I were to still use pimple, I would be defining what controllers are going to be created, and what they need. So you would inject the view and anything from the model layer into the controller so it can use it. This is Inversion Of Control and makes testing much easier. From the Aurn wiki, (which I'll talk about soon):
In real life you wouldn't build a house by transporting the entire hardware store (hopefully) to the construction site so you can access any parts you need. Instead, the foreman (__construct()) asks for the specific parts that will be needed (Door and Window) and goes about procuring them. Your objects should function in the same way; they should ask only for the specific dependencies required to do their jobs. Giving the House access to the entire hardware store is at best poor OOP style and at worst a maintainability nightmare. - From the Auryn Wiki
Enter Auryn
On that note, I'd like to introduce you to something brilliant called Auryn, written by Rdlowrey that I was introduced to over the weekend.
Auryn 'auto-wires' class dependencies based on the class constructor signature. What this means that, for each class requested, Auryn finds it, figures out what it needs in the constructor, creates what it needs first and then creates an instance of the class you asked for originally. Here's how it works:
The Provider recursively instantiates class dependencies based on the parameter type-hints specified in their constructor method signatures.
...and if you know anything about PHP's reflection, you'll know some people call it 'slow'. So here's what Auryn does about that:
You may have heard that "reflection is slow". Let's clear something up: anything can be "too slow" if you're doing it wrong. Reflection is an order of magnitude faster than disk access and several orders of magnitude faster than retrieving information (for example) from a remote database. Additionally, each reflection offers the opportunity to cache the results if you're worried about speed. Auryn caches any reflections it generates to minimize the potential performance impact.
So now we've skipped the "reflection is slow" argument, here's how I've been using it.
How I use Auryn
I make Auryn part of my autoloader. This is so that when a class is asked for, Auryn can go away and read the class and it's dependencies, and it's dependencies' dependencies (etc), and return them all into the class for instantiation. I create the Auyrn object.
$injector = new \Auryn\Provider(new \Auryn\ReflectionPool);
I use a Database Interface as a requirement in the constructor of my database class. So I tell Auryn which concrete implementation to use (this is the part you change if you want to instantiate a different type of database, at a single point in your code, and it'll all still work).
$injector->alias('Library\Database\DatabaseInterface', 'Library\Database\MySQL');
If I wanted to change to MongoDB and I'd written a class for it, I'd simple change Library\Database\MySQL to Library\Database\MongoDB.
Then, I pass the $injector into my router, and when creating the controller / method, this is where the dependencies are automatically resolved.
public function dispatch($injector)
{
// Make sure file / controller exists
// Make sure method called exists
// etc...
// Create the controller with it's required dependencies
$class = $injector->make($controller);
// Call the method (action) in the controller
$class->$action();
}
Finally, answer OP's question
Okay, so using this technique, let's say you have the User controller which requires the User Service (let's say UserModel) which requires Database access.
class UserController
{
protected $userModel;
public function __construct(Model\UserModel $userModel)
{
$this->userModel = $userModel;
}
}
class UserModel
{
protected $db;
public function __construct(Library\DatabaseInterface $db)
{
$this->db = $db;
}
}
If you use the code in the router, Auryn will do the following:
Create the Library\DatabaseInterface, using MySQL as the concrete class (alias'd in the boostrap)
Create the 'UserModel' with the previously created Database injected into it
Create the UserController with the previously created UserModel injected into it
That's the recursion right there, and this is the 'auto-wiring' I was talking about earlier. And this solves OPs problem, because only when the class hierarchy contains the database object as a constructor requirement is the object insantiated, not upon every request.
Also, each class has exactly the requirements they need to function in the constructor, so there are no hidden dependencies like there were with the service locator pattern.
RE: How to make it so that the connect method is called when required. This is really simple.
Make sure that in the constructor of your Database class, you don't instantiate the object, you just pass in it's settings (host, dbname, user, password).
Have a connect method which actually performs the new PDO() object, using the classes' settings.
class MySQL implements DatabaseInterface
{
private $host;
// ...
public function __construct($host, $db, $user, $pass)
{
$this->host = $host;
// etc
}
public function connect()
{
// Return new PDO object with $this->host, $this->db etc
}
}
So now, every class you pass the database to will have this object, but will not have the connection yet because connect() hasn't been called.
In the relevant model which has access to the Database class, you call $this->db->connect(); and then continue with what you want to do.
In essence, you still pass your database object to the classes that require it, using the methods I have described previously, but to decide when to perform the connection on a method-by-method basis, you just run the connect method in the required one. No you don't need a singleton. You just tell it when to connect when you want it to, and it doesn't when you don't tell it to connect.
Old Answer
I'm going to explain a little more in-depth about Dependency Injection Containers, and how they can may help your situation. Note: Understanding the principles of 'MVC' will help significantly here.
The Problem
You want to create some objects, but only certain ones need access to the database. What you're currently doing is creating the database object on each request, which is totally unnecessary, and also totally common before using things like DiC containers.
Two Example Objects
Here's an example of two objects that you may want to create. One needs database access, another doesn't need database access.
/**
* #note: This class requires database access
*/
class User
{
private $database;
// Note you require the *interface* here, so that the database type
// can be switched in the container and this will still work :)
public function __construct(DatabaseInterface $database)
{
$this->database = $database;
}
}
/**
* #note This class doesn't require database access
*/
class Logger
{
// It doesn't matter what this one does, it just doesn't need DB access
public function __construct() { }
}
So, what's the best way to create these objects and handle their relevant dependencies, and also pass in a database object only to the relevant class? Well, lucky for us, these two work together in harmony when using a Dependency Injection Container.
Enter Pimple
Pimple is a really cool dependency injection container (by the makers of the Symfony2 framework) that utilises PHP 5.3+'s closures.
The way that pimple does it is really cool - the object you want isn't instantiated until you ask for it directly. So you can set up a load of new objects, but until you ask for them, they aren't created!
Here's a really simple pimple example, that you create in your boostrap:
// Create the container
$container = new Pimple();
// Create the database - note this isn't *actually* created until you call for it
$container['datastore'] = function() {
return new Database('host','db','user','pass');
};
Then, you add your User object and your Logger object here.
// Create user object with database requirement
// See how we're passing on the container, so we can use $container['datastore']?
$container['User'] = function($container) {
return new User($container['datastore']);
};
// And your logger that doesn't need anything
$container['Logger'] = function() {
return new Logger();
};
Awesome! So.. how do I actually use the $container object?
Good question! So you've already created the $container object in your bootstrap and set up the objects and their required dependencies. In your routing mechanism, you pass the container to your controller.
Note: example rudimentary code
router->route('controller', 'method', $container);
In your controller, you access the $container parameter passed in, and when you ask for the user object from it, you get back a new User object (factory-style), with the database object already injected!
class HomeController extends Controller
{
/**
* I'm guessing 'index' is your default action called
*
* #route /home/index
* #note Dependant on .htaccess / routing mechanism
*/
public function index($container)
{
// So, I want a new User object with database access
$user = $container['User'];
// Say whaaat?! That's it? .. Yep. That's it.
}
}
What you've solved
So, you've now killed multiple birds (not just two) with one stone.
Creating a DB object on each request - Not any more! It's only created when you ask for it because of the closures Pimple uses
Removing 'new' keywords from your controller - Yep, that's right. You've handed this responsibility over to the container.
Note: Before I continue, I want to point out how significant bullet point two is. Without this container, let's say you created 50 user objects throughout your application. Then one day, you want to add a new parameter. OMG - you now need to go through your whole application and add this parameter to every new User(). However, with the DiC - if you're using $container['user'] everywhere, you just add this third param to the container once, and that's it. Yes, that totally is awesome.
The ability to switch out databases - You heard me, the whole point of this is that if you wanted to change from MySQL to PostgreSQL - you change the code in your container to return a new different type of database you've coded, and as long as it all returns the same sort of stuff, that's it! The ability to swap out concrete implementations that everyone always harps on about.
The Important Part
This is one way of using the container, and it's just a start. There are many ways to make this better - for example, instead of handing the container over to every method, you could use reflection / some sort of mapping to decide what parts of the container are required. Automate this and you're golden.
I hope you found this useful. The way I've done it here has at least cut significant amounts of development time for me, and it's good fun to boot!
This is approximately what I use.
class Database {
protected static $connection;
// this could be public if you wanted to be able to get at the core database
// set the class variable if it hasn't been done and return it
protected function getConnection(){
if (!isset(self::$connection)){
self::$connection = new mysqli($args);
}
return self::$connection;
}
// proxy property get to contained object
public function __get($property){
return $this->getConnection()->__get($property);
}
// proxy property set to contained object
public function __set($property, $value){
$this->getConnection()->__set($property, $value);
}
// proxy method calls to the contained object
public function __call($method, $args){
return call_user_func_array(array($this->getConnection(), $method), $args);
}
// proxy static method calls to the contained object
public function __callStatic($method, $args){
$connClass = get_class($this->getConnection());
return call_user_func_array(array($connClass, $method), $args);
}
}
Note it only works if there is a single database in play. If you wanted multiple different databases it would be possible to extend this but beware of late static binding in the getConnection method.
Here is an example of a simple approach:
class Database {
public $connection = null ;
public function __construct($autosetup = false){
if ($autosetup){
$this->setConnection() ;
}
}
public function getProducts(){//Move it to another class if you wish
$this->query($sql_to_get_products);
}
public function query($sql) {
if (!$connection || !$connection->ping()){
$this->setupConnection() ;
}
return $this->connection->query($sql);
}
public function setConnection(){
$this->connection = new MySQLi($a, $b, $c, $d) ;
}
public function connectionAvailable(){
return ($connection && $connection->ping()) ;
}
}
Look into using a dependency injection container, something like Pimple would be nice place to start. With a dependency injection container you 'teach' the container how to create the objects in your application, they're not instantiated until you ask for them. With Pimple, you can configure a resource to be shared so that it's only ever instantiated once during the request no matter how often you ask the container for it.
You can setup your classes to accept the container in their constructor or use a setter method to inject into your class.
A simplified example could look like this:
<?php
// somewhere in your application bootstrap
$container = new Pimple();
$container['db'] = $container->share(
function ($c) {
return new Database();
}
);
// somewhere else in your application
$foo = new Foo($container);
// somewhere in the Foo class definition
$bar = $this->container['db']->getBars();
Hope it helps.
You got some great answers already, with the majority concentrating on the aspect of injecting dependencies (which is a good thing), and only creating objects on demand.
The other aspect is the more important one: Do not put code that does any heavy work into your constructors. In case of a database object, this means: Do not connect to the database inside the constructor.
Why is this more important? Because not creating a database object because the using object also gets not created is no real optimization if the using object gets always created, but does not always run queries.
Creating an object in PHP is reasonable fast. The class code usually is available in the opcode cache, so it only triggers a call to the autoloader and then allocates some bytes in memory for the objects' properties. The constructor will run after that. If the only thing it does is copying the constructor parameters to local property variables, this is even optimized by PHP with "copy-on-write" references. So there is no real benefit if this object does not get created in the first place, if you cannot avoid it. If you can: even better.
I come from the world of Java. Java is resident in memory accross stateless HTML requests. PHP is not. That is a whole different story - and what I like about PHP.
I simply use:
$conn = #pg_connect(DBConnection);
the DBConnection is a definition containing the information about the host etc..
The # assures that the current connection is used or a new one is created. How can I do it more easily?
The data how to connect to the database is stable. The connection itself might be recreated during a request. Why should I program better then the people of PHP and recreate the #? They did that for the PHP community, let's use it.
By the way, never put heavy objects in a constructor and never let the constructor do some heavy job nor let it happen that an exception can be thrown during construction of an object. You might have an unfinished object resident in your memory. An init-method is to be preferred. I agree on that with Henrique Barcelos.
This is the way I am using mysqli. Database object behaves the same as mysqli object, can add my own methods or override existing ones, and the only difference is that the actual connection to database is not established when you create the object but on first call to method or property that needs the connection.
class Database {
private $arguments = array();
private $link = null;
public function __construct() {
$this->arguments = func_get_args();
}
public function __call( $method, $arguments ) {
return call_user_func_array( array( $this->link(), $method ), $arguments );
}
public function __get( $property ) {
return $this->link()->$property;
}
public function __set( $property, $value ){
$this->link()->$property = $value;
}
private function connect() {
$this->link = call_user_func_array( 'mysqli_connect', $this->arguments );
}
private function link() {
if ( $this->link === null ) $this->connect();
return $this->link;
}
}
Another way to achieve the same behavior is with use of mysqli_init() and mysqli_real_connect() methods, constructor initializes the object with mysqli_init(), and when you need a real connection the mysqli_real_connect() method is used.
class Database {
private $arguments = array();
public function __construct() {
$this->arguments = array_merge( array( 'link' => mysqli_init() ), func_get_args() );
}
public function __call( $method, $arguments ) {
return call_user_func_array( array( $this->link(), $method ), $arguments );
}
public function __get( $property ) {
return $this->link()->$property;
}
public function __set( $property, $value ) {
$this->link()->$property = $value;
}
private function connect() {
call_user_func_array( 'mysqli_real_connect', $this->arguments );
}
private function link() {
if ( !#$this->arguments['link']->thread_id ) $this->connect();
return $this->arguments['link'];
}
}
I tested memory consumption for both approaches and got quite unexpected results, the second approach uses less resources when connects to database and executes queries.
interface IDatabase {
function connect();
}
class Database implements IDatabase
{
private $db_type;
private $db_host;
private $db_name;
private $db_user;
private $db_pass;
private $connection = null;
public function __construct($db_type, $db_host, $db_name, $db_user, $db_pass)
{
$this->db_type = $db_type;
$this->db_host = $db_host;
$this->db_name = $db_name;
$this->db_user = $db_user;
$this->db_pass = $db_pass;
}
public function connect()
{
if ($this->connection === null) {
try {
$this->connection = new PDO($this->db_type.':host='.$this->db_host.';dbname='.$this->db_name, $this->db_user, $this->db_pass);
$this->connection->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
return $this->connection;
} catch (PDOException $e) {
return $e;
}
} else {
return $this->connection;
}
}
}
How about this? In connect(), check if a connection has already been established, if yes, return it, if not, create it and return it. This will prevent you from having TOO many connections open. Let's say, in your controller action, you want to call two methods of UserRepository (that depends on the Database), getUsers() and getBlockedUsers(), if you call these methods, connect() will be called in each one of them, with this check in place it will return the already existing instance.
You could use an singleton pattern to achive this and request everytime you need the database a database object. This results in something like this
$db = DB::instance();
where DB::instance is declared something like this
class DB {
//...
private static $instance;
public static function instance() {
if (self::$instance == null) {
self::$instance = new self();
}
}
//...
}
<?php
mysql_select_db('foo',mysql_connect('localhost','root',''))or die(mysql_error());
session_start();
function antiinjection($data)
{
$filter_sql = stripcslashes(strip_tags(htmlspecialchars($data,ENT_QUOTES)));
return $filter_sql;
}
$username = antiinjection($_POST['username']);
$password = antiinjection($_POST['password']);
/* student */
$query = "SELECT * FROM student WHERE username='$username' AND password='$password'";
$result = mysql_query($query)or die(mysql_error());
$row = mysql_fetch_array($result);
$num_row = mysql_num_rows($result);
/* teacher */
$query_teacher = mysql_query("SELECT * FROM teacher WHERE username='$username' AND password='$password'")or die(mysql_error());
$num_row_teacher = mysql_num_rows($query_teacher);
$row_teahcer = mysql_fetch_array($query_teacher);
if( $num_row > 0 ) {
$_SESSION['id']=$row['student_id'];
echo 'true_student';
}else if ($num_row_teacher > 0){
$_SESSION['id']=$row_teahcer['teacher_id'];
echo 'true';
}else{
echo 'false';
}
?>
and in the php file insert javascript
<script>
jQuery(document).ready(function(){
jQuery("#login_form1").submit(function(e){
e.preventDefault();
var formData = jQuery(this).serialize();
$.ajax({
type: "POST",
url: "login.php",
data: formData,
success: function(html){
if(html=='true')
{
window.location = 'folder_a/index.php';
}else if (html == 'true_student'){
window.location = 'folder_b/index.php';
}else
{
{ header: 'Login Failed' };
}
}
});
return false;
});
});
</script>
another connection
<?php
class DbConnector {
var $theQuery;
var $link;
function DbConnector(){
// Get the main settings from the array we just loaded
$host = 'localhost';
$db = 'db_lms1';
$user = 'root';
$pass = '';
// Connect to the database
$this->link = mysql_connect($host, $user, $pass);
mysql_select_db($db);
register_shutdown_function(array(&$this, 'close'));
}
//*** Function: query, Purpose: Execute a database query ***
function query($query) {
$this->theQuery = $query;
return mysql_query($query, $this->link);
}
//*** Function: fetchArray, Purpose: Get array of query results ***
function fetchArray($result) {
return mysql_fetch_array($result);
}
//*** Function: close, Purpose: Close the connection ***
function close() {
mysql_close($this->link);
}
}
?>
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);
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