I have a CMS that is failing when more than one person is logged in. I think the problem may be that I'm not closing databases properly. Here is the basic setup:
I have a master class called Mysql. The __construct() method looks something like this:
class Mysql {
protected $conn;
function __construct() {
if(!$this->conn) $this->conn = New mysqli(SITE_HOSTNAME, SITE_USERNAME, SITE_PASSWORD, SITE_DATABASE);
}
All of my classes are descendants of this class, and so whenever they are instantiated, they get their own connection.
I'm using prepared statements to protect against sql injection. A sample method might look like this:
function foo($blog = 0) {
$query = "SELECT catid, catname
FROM category
WHERE blog = ?
ORDER BY catname ASC";
$result = array();
if($stmt = $this->conn->prepare($query)) {
$stmt->bind_param('i', $blog);
$stmt->execute();
$stmt->bind_result($catid, $catname);
while($stmt->fetch()) $result[$catid] = stripslashes($catname);
$stmt->close();
return $result;
}
}
The Mysql __destruct() method looks like this:
function __destruct() {
if($this->conn) $this->conn->close();
}
Is my problem that I am not closing my connections properly, or that I do not have enough active connections?
My provider says that I have 30 simultaneous connections available. Not enough?
Thanks for your help.
The Problem
All of my classes are descendants of this class, and so whenever they
are instantiated, they get their own connection.
The problem with the way you are doing it is that every single instance of any class that inherits Mysql is opening a connection to the Mysql server that lives until the request is completed, or the variable destructed (unless you are killing these objects manually, that's at the end of the request). If you have 30 instance of classes like this, then you have maxed out your connections.
Fixing The Problem
Your classes shouldn't all be inheriting this Mysql class that represents your interface to the database.
Instead, you should be passing a single instance of this Mysql class where it's needed.
There are two ways this could be done effectively:
Dependency Injection
class SomeClass {
protected $db;
public function __construct(Mysql &$db) {
$this->db = $db;
}
public function functionThatNeedsDatabase() {
$this->db->doSomethingWithTheDatabase();
}
}
$db = new Mysql(); //A single instance of Mysql class has been created.
$someClass = new SomeClass($db);
$someClass->functionThatNeedsDatabase();
Pass to Method When Needed
class SomeClass {
public function functionThatNeedsDatabase(Mysql &$db) {
$db->doSomethingWithTheDatabase();
}
}
$db = new Mysql(); //A single instance
$someClass = new SomeClass();
$someClass->functionThatNeedsDatabase($db);
Your problem is "All of my classes are descendants of this class, and so whenever they are instantiated, they get their own connection." In PHP connection are automatically closed when the script ends. You really only need 1 connection per user. You should create an instance of your DB class and pass that object into all the classes that need to use it (Dependency Injection pattern).
30 connections is not a whole lot, but that is sufficient for a lot of traffic. I would avoid using persistent connections. Read the documentation thoroughly on that, there are plenty of warnings.
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 have a class userdb in which I am declaring a function that returns the connection to the database:
return $con = new PDO("mysql:host=$host;dbname=$db", $user, $pass);
I have various functions, even across other classes, where I have to access $con (e.g. to pass a query or to fetch data), but I can't access this variable.
Is there a better way to define and use a database class? Remember that I have other classes where I need to access the userdb class.
I would advise you to use the Singleton Pattern for this:
In your userdb class, declare a static property $scon:
private static $scon;
and assuming the function you mention above is named createConnection(), you should create the folowing static method:
public static function connect() {
if (empty(self::$scon)) {
$instance = new userdb();
self::$scon = $indtance->createConnection();
}
return self::$scon;
}
With this, you will be able to access your userdb connection with:
userdb::connect();
Also since this is a singleton, it will only connect once, and use that connection until the end of the script.
Note (on dependency injection): Since #KevinM1 mentioned Dependency Injection, I must add that it is also a possible, and far superior solution. It requires you to create a setConnection() method (or an Abstract ancestor) for all your classes using a database connection, and during the instatiation of these classes you may use a Factory to add the required connection to the object. This should be wrapped inside some class loader, which is avare of your model structure.
See, peace of cake, but for small and fast developement I would stick with the Singleton ;)
If it's in a class, store the instance in a property:
class userDB
{
public $dbCon = false;//because you want to access the instance
//from outside the class, I have made the property public
function connect()
{
$con = new PDO("mysql:host=$host;dbname=$db", $user, $pass);
$this->dbCon = $con;
}
}
TO access it outside of the class:
$useDBInstance->dbCon;
return $this->con
return this way from your class and call it this way..
$this->classObject->con->prepare();
Checkout my video tutorial + code for an alternative to global PHP variables.
You're doing it wrong there. You need to use a static variable if you plan to create your connection in a function and store it there. Otherwise you'll keep connecting on every function call. My tutorial explains this very concept of static variables within regular functions.
If it's not clear enough, let me know and I'll try to answer your questions.
Here's some code to accompany this:
/**
* Arguments are none or [$db, [$user, [$pass[, $host]]]].
*
* #return PDO
*/
function PdoDb(){
static $con = null; // I'm explicit :)
// Every time you pass Arguments you reconnect
if(func_num_args()){
$args = array_pad(func_get_args(), 4, null);
list($db, $user, $pass, $host) = $args;
if(empty($user)) $user = 'root';
if(empty($host)) $host = 'localhost';
$con = new PDO("mysql:host={$host};dbname={$db}", $user, $pass);
}
if(empty($con)){
trigger_error('Provide arguments to connect first.', E_USER_ERROR);
return null;
}
return $con;
}
// First run (provide arguments to connect)
PdoDb($db, $user, $pass, $host);
PdoDb($db); // Works if you connect root#localhost with no password
// From here on (it returns PDO)
PdoDb()->DoStuffOfPdo();
Once connected it stays that way. But you can reconnect at will to by providing arguments.
Well, $con will already be an object, as it's instantiating a new PDO object. Unless you're trying to add functionality to your PDO object, wrapping it is pointless.
That said, the best way to share your userdb/PDO object (depending on whether or not you stick with the wrapper) with other objects is to use Dependency Injection. That's a fancy term for passing your db to whatever object needs it. Since objects are defaultly passed by reference in PHP, if you create your db object first, all objects that receive it as a constructor/method argument will be using that same single instance.
EDIT: Link to Dependency Injection implementation
EDIT2: Clarification on DI in small projects -
The normal DI pattern generally requires a special object called a DI Container. This is a special use object that automatically injects the dependency into the object that needs it. For small projects, it's overkill. The simple, low complexity version of DI is simply:
class SomeClass {
protected $db;
public function __construct($db) {
$this->db = $db;
}
}
class SomeClass2 {
public function SomeMethod($db) {
// do something with the db
}
}
$db = new PDO(/* connection string */);
$obj = new SomeClass($db, /* other constructor args */);
// or
$obj2 = new SomeClass2(/* constructor args */);
$obj2->someMethod($db, /* method args */);
The magic is that since objects are passed by reference by default in PHP, $obj and $obj2 are using the same db connection.
The whole idea is to not blow apart scope or encapsulation by having a static method, and to ensure that classes and their methods are up front about what they require in order to work.
Singletons do the exact opposite. They're accessed through static methods, which bypass scope, and since they're invoked and not passed, they never show up in method signatures, so anyone not familiar with the code won't be aware of that hidden requirement. Even Erich Gamma, one of the people who helped codify the Singleton Pattern has regrets about it:
I'm in favor of dropping Singleton. Its use is almost always a design smell.
In PHP, where there's no concept of shared memory, and where scripts execute once per request, the only reason to want to use a singleton is to have easy access to a single resource. Since objects are passed by reference, a single instance can be shared with multiple objects naturally. From there, it's about good design and delegation.
use singlton class implimentation
class connectdb
{
protected static $_instance = NULL;
private function __construct()
{
}
public function getinstance()
{
if (null === self::$_instance) {
self::$_instance = new self();
}
return self::$_instance;
}
public function connect()
{
$this->connection =new PDO("mysql:host=$host;dbname=$db", $user, $pass);
}
}
for using a variable within a class function or independent function you need to place a global keyword
$conn=mysql_connect();
function test(){
global $conn;
}
now $conn will be available within the scope of test function, and it will be available everywhere when defined at the top of the script. For class also you need to do the same thing, make a object of a class and declare it as global within a function
I'm pretty new to both PDO and OOP. I'm trying to write a class that connects to a database and updates inserts and modifies it. I have several questions:
Is it good practices to connect to the database in the constructor?
Should the one class be updating, inserting, modifying and connecting or should it be split up into several classes?
Why is runQuery not working? I assume its because $pdo is defined in a different scope. How would I get this working?
If the class is include at the top of every page does that mean it will reconnect to the database every time a new page is loaded and will that cause security issues?
Apologies for the overload of questions. Thanks in advance for any answers.
<?php
class Login{
private $_username;
private $_password;
private $_host;
private $_database;
private $_driver;
//Connect to the database
function __construct($configFile){
$connectionDetails = parse_ini_file($configFile);
$this->_username = $connectionDetails['username'];
$this->_password = $connectionDetails['password'];
$this->_host = $connectionDetails['host'];
$this->_database = $connectionDetails['database'];
$this->_driver = $connectionDetails['driver'];
$pdo = new PDO("$this->_driver:host=$this->_host;dbname=$this->_database", $this->_username, $this->_password);
}
public function loginAllowed($user, $pw){
$sth = $pdo->setFetchMode(PDO::FETCH_ASSOC);
print_r($sth);
}
public function runQuery($query, $params){
$sth = $this->pdo->prepare($query);
$sth->execute($params);
}
}
Because $pdo is a local variable in your constructor and your method loginAllowed. You should make it an instance variable (private $pdo) so you can call it through $this->pdo. I also suggest to use type hinting here, give the PDO class as a parameter in the constructor.
Example
<?php
class Login {
private $pdo;
// Your other instance variables
public function __construct(PDO $pdo)
{
$this->pdo = $pdo;
}
// Your other methods
}
$pdo = new PDO("...");
$login = new Login($pdo);
You shouldn't bother your class with reading settings and initialising your database connection (definitely read about separation of concerns), keep it out of your class. Just give the PDO object as a parameter (I used type hinting, that way you are forced to provide an object of the PDO type). Another advantage is that you can now make sure you have only one active database connection (you can manage this in your code base), creating multiple connections is unnecessary and definitely unwanted (performance wise).
Also use require_once to include your class definition. Otherwise you will get many errors about redeclaring (and you'd want to avoid that).
Connect to the db wherever you find it most convenient. Just try to make sure there's only ONE connection. More connections to the same db is a waste of time and resources.
The class you refer to is called a model in the MVC architecture. It usually does all the operations on a given table. I see nothing wrong in using a single class for all your needs - as long as the code is readable and maintainable.
It's not working because $pdo is a local variable. In the ctor, instantiate $this->pdo instead.
Including a class is not equivalent to instantiating it. A new instance will make another connection. Including it multiple times will only give you a multiple declaration error :). Use require_once instead. If you wish to use the instance in multiple files, I strongly suggest you do a quick search regarding the Singleton pattern. Using a singleton object will ensure you always have only one instance of your model object.
Don't bother with all the random stuff, just replacethis in your construct:
$pdo = new PDO("$this->_driver:host=$this->_host;dbname=$this->_database", $this->_username, $this->_password);
with
$this->pdo = new PDO("$this->_driver:host=$this->_host;dbname=$this->_database", $this->_username, $this->_password);
and reference it as $this->pdo from now on. As simple as that!!
1) Is it good practices to connect to the database in the constructor?
No good.just connect befor query
if($this->pdo == null) {
$this->pdo = new PDO("....");
}
2) Should the one class be updating, inserting, modifying and connecting or should it be split up into several classes?
Add methods for class
3) Why is runQuery not working? I assume its because $pdo is defined in a different scope. How would I get this working?
use $this->pdo instead
4) If the class is include at the top of every page does that mean it will reconnect to the database every time a new page is loaded and will that cause security issues?
use static $pdo
then self::$pdo would be the only one connector
if(self::$pdo == null) {
self::$pdo = new PDO("....");
}
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.