Perhaps you can help. I have a main class that creates a MySql connection. Then I extend this class. I wasn't able to access the connection unless I did a parent::__construct(); and recently while doing this I got an error message that I was out of connections.
So how do program this so it doesn't run out of connections and can access the database connection.
class Common
{
var $mysql;
function __construct()
{
$this->mysql=new mysqli($this->dbHOST, $this->dbUSERNAME, $this->dbPASSWORD, $this->dbNAME);
}
}
class Role extends Common {
function __construct()
{
parent::__construct();
}
}
I think there is a fundamental problem with your class structure: You don't need a connection per object, you only need a copy of the connection resource per object.
My preferred way out of this is to create a database handler that has a singleton call. Now it can be called anywhere and it will always return the same connection handler. This is also an excellent way to hide automatic initialization.
The solution was borne out of the realization that a class representing a database row is actually quite different from a class that is a database connection. An app will deal with many many rows but rarely, if ever, will deal with more than one connection. Another way of putting this is the difference between the IS-A and HAS-A definitions: it doesn't make sense to say "a database row class IS-A database connection". It does make sense to say "a datbase row class HAS-A database connection".
Make sure you close the connection when the object is destroyed. That is, add a __destruct() method that closes the connection.
If the Common class is the one that opens the connection in its __construct() method, then it should be the one to close it in its __destruct() method. If you don't define a __destruct() method on the Role class, then it looks like PHP won't call the parent's __destruct() automatically. (I haven't tested this, though.) A simple solution is to add a stub __destruct() method that just calls parent::__destruct().
Related
I know we always have to close db connection at the end. Let's I have a class and there is four methods and each consists of db queries. Now my question is
Should I create a connection and close it in every different methods
or create the connection in the constructor of the class? If I create
the connection in the constructor then where will I close it. Because
If I close that in any function no other method can access it.
If I create new connection for every method then no of connections may be very high. Then where will I create and close the function proper way?
If you open it, then you need to close it.
As long as you close the connection, you can close it where you want. It seems like maybe your closing woes are more about the design of the procedures of your program. Just because the database call uses a connection doesn't mean it has to be opened and closed right there with it.
Say you might want to reuse a $mysqli variable that's holding a connection. You can pass that connection to a function and either return it or close it inside. In this way, you can isolate the main activity of the database call in the body of the function without having to worry too much about the opening and closing of everything.
Using that technique, it's possible to reuse a connection for multiple queries, contained each inside their own method. Maybe you would be better off opening a class and passing a $mysqli connection to it, as needed.
This depends on your program and your choices about how it will work.
If you are developing a program, and you're curious about the impact of your opening and closing actions, you can call http://php.net/manual/en/mysqli.stat.php or a similar function. If you are opening many threads and not closing them, then you would see the thread count escalate in the answer from mysqli_stat().
The calls may not close, for example, if you have a poorly designed query that runs away from you; the scope of the connection object should close naturally with the end of the script.
Because of the reference-counting system of php it's not necessary to close the connection, it will be freed automatically (unless you open persistent db links), so it shouldn't cause a headache.
You should open the connection only once btw.
Please take into consider transaction concept. Say for example you methods are being called in a sequence, it makes sense to open a connection and keep it open
If there is delay in call of other methods, i would not advice you to keep connection suspended especially if multiple people are going to access the application
Best way would be to implement classes and extend it to your functional class containing methods. Constructor of the extended class can call to the connection function and the destructor can call to disconnect whenever the object is set to NULL.
Or
As your question states, have two functions in base class having construction and other having destruction.
Call to the constructor function before using your connection and destroy it after using.
Example would be:
class bar{
protected function connect(){
#connect to db
}
protected function disconnect(){
#disconnect db
}
class foo extends bar{
function func1 () {
$this->connect();
#Code
$this->disconnect();
}
function func2() {
$this->connect();
#Code
$this->disconnect();
}
function func3() {
$this->connect();
#Code
$this->disconnect();
}
function func4() {
$this->connect();
#Code
$this->disconnect();
}
?>
I came across this piece of code that's supposed to ensure that only one database connection is created per browser so that the application sees improved performance due to the reduced number of calls to the database.
I believe I do understand the logic how this is ensured but I just need to confirm that my understanding on this is correct and complete. So, please help me with the explanation details.
Also is there a better practice than this when making database connection/calls ?
class Database {
private static $dsn = 'mysql:host=localhost;dbname=mydatabase';
private static $username = 'dbuser';
private static $password = 'dbpass';
private static $db;
private function __construct() {}
public static function getDB ()
{
if (!isset(self::$db)) {
try {
self::$db = new PDO(self::$dsn,
self::$username,
self::$password);
} catch (PDOException $e) {
$error_message = $e->getMessage();
include('../errors/database_error.php');
exit();
}
}
return self::$db;
}
}
As #raina77ow noted in a comment, this is called the Singleton pattern. Here's some explanation:
The point of being a Singleton is that no calling code can create more than one $db. And to provide global access from anywhere in your code to the created $db.
Static class variables exist as exactly one instance per class. Therefore you can't create multiple $db connections even if you could instantiate this class as an object.
Since there's no purpose to instantiating the class as an object (that would only be useful if the class had non-static variables that existed per object instance), the class constructor is not needed. To prevent calling code from being tempted to call new, the constructor is made private. (Strictly speaking, there would be no harm in doing so, because the only class variables are static anyway.)
Note that your implementation is missing the magic __clone and __wakeup methods. Without these your Singleton can still be cloned and unserialized. So technically, your Singleton is not enforcing singularity properly.
Here are some additional thoughts:
Singleton classes (or any classes with static usage) are notoriously difficult to integrate into automated testing. Since they're static, you can initialize them once and they retain their state for the duration of your test suite. If you use non-static classes, you can re-initialize them each time you use new to instantiate a new object.
An alternative design is to use a Registry pattern, and some kind of bootstrap for your application that creates a non-static db instance and stores it in the registry.
If you do use Singleton, it's sometimes recommended to declare the Singleton class final so no subclasses can override the behavior or get access to the private data.
Your database credentials are hard-coded as private data in the class definition. I wouldn't do that. If your Apache PHP handler gets misconfigured, users could see your PHP source code, and then they'd have your database password. Put the database connection parameters into a config file, and store the config file outside your Apache document root.
Outputting the db connection error message verbatim can reveal information to users. Log the PDO error message, but put out a friendly message for users like "we're experiencing a problem, please notify the site administrator."
You don't need to terminate PHP blocks with ?> in a class definition file. It adds a risk that you could have a space or a newline after the close, which will become whitespace in your application and throw off your layout. Those types of errors are maddening to track down.
Lets put the case that we've got two separate classes, each owns a mysqli object to use for database operations.
class A{
protected $mysqliObject;
public function __constructor(){
$this->mysqliObject=new mysqli(...)
}
public function doSomething(){
$this->mysqliObject->query(...);
}
}
class B{
protected $mysqliObject;
public function __constructor(){
$this->mysqliObject=new mysqli(...)
}
public function doSomething(){
$this->mysqliObject->query(...);
}
}
The doSomething() methods use the $mysqliObject for a database query (SELECT, UPDATE, DELETE, etc...). I want to do the following outside:
// Start point
$aObject=new A();
$bObject=new B();
$aObject->doSomething();
$bObject->doSomething();
// End point
...but I want to roll back both queries if any of them fails. How can I do that?
Can I create a brand new mysqli object at "Start point", and use it to commit or rollback at "End point" the database query of class A and class B?
Do I have to create outside, and pass the same $mysqliObject to the __constructor() of class A and class B, and use that to rollback or commit (outside).
Would like to see more techniques with pro-con's.
Each database connection object you have represents a different connection to the database, even if the connection is to the same database server. Each connection is completely independent of each other, so a transaction started in one connection will be invisible to the other connection.
If all your database access is to the same server, then just create a single connection and pass it to anything that needs access to the connection. Then the transaction will be application-wide.
class ClassThatNeedsDbAccess
{
protected $connection = NULL;
protected function doQuery ($query)
{
return ($this -> connection -> execute ($query));
}
public function __construct (PDO $connection)
{
$this -> connection = $connection;
}
}
class OtherClassThatNeedsDbAccess extends ClassThatNeedsDbAccess
{
}
$myDb = new PDO ('dsn_goes_here');
$obj1 = new ClassThatNeedsDbAccess ($myDb);
$obj2 = new OtherClassThatNeedsDbAccess ($myDb);
If you're talking to different database servers, then you probably should wrap all the connections in an object that can coordinate the database activity. It will be that object's responsibility to track which database connection has a transaction in flight.
Use one MySQL object - connection for all your business logic... take a look at singleton pattern. You can pass it to constructor or you could use static class method to get mysql object.
Then it's a matter of you where you start end transaction, connection must be the same. Best would be abstract it into some general database access layer.
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
I am making my first steps in the OOP world - please bear with me.
I know that having many ongoing mySQL connections open at the same time can be fatal for performance, so it should be a good idea to make a database class that takes this into account.
Is $this->session->write(...); going to result in a new mySQL connection being opened each time?
Or is that up to the "persistent connection" feature in mySQL?
Here's the code:
abstract class database {
function __construct() {
//mysql_connect()
}
}
class session extends database {
function write () {
// mysql_query(--.)
}
}
Is session handler some kind of specialized type of database? It is not, so don't use inheritance (a is a relationship). Session handler uses database so you should use composition (a has a relationship):
class Session {
protected $db;
public function __construct(DB $db) {
$this->db = $db;
}
public function write() {
$this->db->query(...);
}
}
$db = new DB(...);
$session = new Session($db);
Also, don't use mysql_*() functions. Use much more powerful PDO.
Returning to your question... mysql_connect() will be executed every time you create a new Database object. However in this case Session is an object of type Database so every time you write new Database() or new Session() the constructor is invoked, therefore mysql_connect() is invoked as well.
PS. mysql_connect() function won't create a new connection if specified connection already exists. Check 4th argument of this function to learn more.
mysql_query will create a new connection only if no previous mysql connection has been made. Otherwise, it will either use the connection you specify or the last connection opened with mysql_connect. http://php.net/manual/en/function.mysql-query.php
Why not
class database {
function __construct() {
//mysql_connect()
}
function write() {
//query the DB
}
}
I'm not sure of the syntax, I don't do OOP PHP. Anyway, in your structure above a new connection would be opened for each "session" instance so assuming you only create one instance of "session" you won't be openeing loads of database connections.