Go Back   CodingForums.com > :: Server side development > PHP

Before you post, read our: Rules & Posting Guidelines

Reply
 
Thread Tools Rate Thread
Enjoy an ad free experience by logging in. Not a member yet? Register.
Old 09-13-2012, 06:23 PM   PM User | #1
Oatley
New Coder

 
Join Date: Sep 2012
Posts: 70
Thanks: 56
Thanked 0 Times in 0 Posts
Oatley is an unknown quantity at this point
Connecting to a database through various classes

Hello,

I'm wondering about the best practice involved for connecting to a database throughout several other classes in OOP.

I have a connection class, which I have created as a singleton pattern like so

PHP Code:
class Connection {
      const 
SERVER "xxxxxxxxxxxxxxxxxxxxxx";
      const 
USER "xxxxxxxxxxxxxxxxxxxxxx";
      const 
PASSWORD "xxxxxxxxxxxxxxxxxxxxxx";
      const 
DBNAME "xxxxxxxxxxxxxxxxxxxxxx";

      
/**
      * Store a single instance of the database
       * */
       
private static $instance;

       
/**
       * Getter method for returning a single instance of the class
       **/
       
public static function getConnection() {
         if(!isset(
self::$instance)) {
           
$CONN mysql_connect(self::SERVERself::USERself::PASSWORD) or die ('Unable to select database: '.mysql_error ());
           
$DB mysql_select_db(self::DBNAME,$CONN);
          }
          return 
self::$instance;
        }

PHP Code:
//Connect to database
$connection Connection::getConnection(); 
Now all of my classes on my site will need database access to run various queries, so what is best practice here?

For each of these classes to extend the connection class or is there a better way? Maybe passing in some connection object to each of these classes?

Can anyone please help me to show how I can use my singleton connection class within in another class that runs a query to the database? An example would be great if that's not too much to ask for.

Thank you for reading this
Oatley is offline   Reply With Quote
Old 09-13-2012, 06:47 PM   PM User | #2
Fou-Lu
God Emperor


 
Fou-Lu's Avatar
 
Join Date: Sep 2002
Location: Saskatoon, Saskatchewan
Posts: 15,645
Thanks: 4
Thanked 2,450 Times in 2,419 Posts
Fou-Lu is a name known to allFou-Lu is a name known to allFou-Lu is a name known to allFou-Lu is a name known to allFou-Lu is a name known to allFou-Lu is a name known to all
Unless each of the classes are a Connection class, then no you wouldn't extend it as that doesn't make any sense (ie: a User is not a type of Connection).
You need to determine if your classes are aggregates or composites using the connection. If they are aggregates, then you simply factory a connection within the constructor (or whatever method you want), particularly if they allow alternate connections. If they are composites then you pass an existing Connection object to the construction of the new class. Given that the singleton is specific to only a single instance regardless of credentials, this to me would be governed by a composite design. If each class were capable of choosing its own storage, I'd still use a factory but leave those details up to the class by letting it aggregate a connection itself based on its configurations.

Since you're already using OOP here, drop the use of mysql library and use either PDO or MySQLi. Don't forget to add a protected or private constructor override, otherwise you can indefinitely create Connection objects, even though there are no specific properties here unique to each connection, its probably not wise to have a ton of unnecessary class object's hanging around doing nothing in particular.
Fou-Lu is offline   Reply With Quote
Users who have thanked Fou-Lu for this post:
Oatley (09-14-2012)
Old 09-14-2012, 01:27 PM   PM User | #3
Oatley
New Coder

 
Join Date: Sep 2012
Posts: 70
Thanks: 56
Thanked 0 Times in 0 Posts
Oatley is an unknown quantity at this point
First of all than you so much for the reply. I'm a little confused on some of it though to be honest as I've only just in the last few days started to look at design patterns and really only started with the singleton design pattern so any further advice you could offer would be great:

Quote:
Unless each of the classes are a Connection class, then no you wouldn't extend it as that doesn't make any sense (ie: a User is not a type of Connection)
Thanks, that makes sense.

Quote:
You need to determine if your classes are aggregates or composites using the connection. If they are aggregates, then you simply factory a connection within the constructor (or whatever method you want), particularly if they allow alternate connections.If they are composites then you pass an existing Connection object to the construction of the new class. Given that the singleton is specific to only a single instance regardless of credentials, this to me would be governed by a composite design. If each class were capable of choosing its own storage, I'd still use a factory but leave those details up to the class by letting it aggregate a connection itself based on its configurations.
When you say alternate connections do you mean a MYSQLi or PDO connection for example? I would only be using PDO. I've never read up on
aggregates or composites and only started learning design patterns. Is there any example that you could kindly post a link to that shows how to use a connection in this way if you know of one, as I'm not really understanding and maybe a demo on a link would help me here.

Quote:
Since you're already using OOP here, drop the use of mysql library and use either PDO or MySQLi. Don't forget to add a protected or private constructor override, otherwise you can indefinitely create Connection objects, even though there are no specific properties here unique to each connection, its probably not wise to have a ton of unnecessary class object's hanging around doing nothing in particular
Yes will be changing to PDO thanks for the advice

Thank you
Oatley is offline   Reply With Quote
Old 09-14-2012, 04:40 PM   PM User | #4
Fou-Lu
God Emperor


 
Fou-Lu's Avatar
 
Join Date: Sep 2002
Location: Saskatoon, Saskatchewan
Posts: 15,645
Thanks: 4
Thanked 2,450 Times in 2,419 Posts
Fou-Lu is a name known to allFou-Lu is a name known to allFou-Lu is a name known to allFou-Lu is a name known to allFou-Lu is a name known to allFou-Lu is a name known to all
Easiest way I can think of it is:
If you explicitly rely on a connection of a specific type, pass that into the object:
PHP Code:
$con Connection::getInstance();
$user = new User($con); 
If each class can explicitly make its own connection, its aggregated by the class:
PHP Code:
class User
{
    private 
$con;
    public function 
__construct()
    {
        
$this->con Connection::getInstance();
    }

This is more useful if Connection can be established with multiple connections. In the example of a singleton, it doesn't matter if its passed in or if its constructed within as you will always end up with the same connection. Aggregate it within the class if you want to have the ability to construct an alternate connection. I'd pass it into the class if it must rely on a specific connection (which may or may not be reused by other classes).

So if your individual class is capable of providing alternate storage instructions, I'd allow it to do so by creating it within. If it cannot provide alternate instructions, then I'd pass it as a parameter.
Fou-Lu is offline   Reply With Quote
Users who have thanked Fou-Lu for this post:
Oatley (09-14-2012)
Old 09-14-2012, 08:49 PM   PM User | #5
Oatley
New Coder

 
Join Date: Sep 2012
Posts: 70
Thanks: 56
Thanked 0 Times in 0 Posts
Oatley is an unknown quantity at this point
Thanks again, that's great and really helped me understand it all much better. Just have a couple of last things to check to make sure I've understood it ok

Quote:
So if your individual class is capable of providing alternate storage instructions, I'd allow it to do so by creating it within. If it cannot provide alternate instructions, then I'd pass it as a parameter.
When you talk about alternate storage instructions do you mean alternate database connections throughout my site?

So if I used a PDO connection only throughout the site then I would pass it in as a parameter, but if I wanted to maybe pass the connection in maybe as EITHER a PDO connection or Mysqli connection for example I'd create the connection from within the class? Or have I not understanding it properly here?

Also one last question as well. Any child classes that extend a class that it's parent already has a connection I take it there is no need to create another connection in the child class?

Thank you again.
Oatley is offline   Reply With Quote
Old 09-14-2012, 09:22 PM   PM User | #6
Fou-Lu
God Emperor


 
Fou-Lu's Avatar
 
Join Date: Sep 2002
Location: Saskatoon, Saskatchewan
Posts: 15,645
Thanks: 4
Thanked 2,450 Times in 2,419 Posts
Fou-Lu is a name known to allFou-Lu is a name known to allFou-Lu is a name known to allFou-Lu is a name known to allFou-Lu is a name known to allFou-Lu is a name known to all
Bring the concept of storage up to a more abstract level. It doesn't matter what your storage is, it can be filesystem files or database calls. When I say alternative, I simply mean different or controlled by this object (as in you are not limited to storing only in a database or only in a filesystem, you can store in both or multiple of either database or filesystem both local and remote).

What I mean is that if you have anything that can control its own storage and choose to write to different storage be that database or filesystem, then let it do so by constructing its own handling (ie, its own connection object). If you dictate that the application must use a specific storage regardless of what the storage is or what the classes are, then I'd recommend that they be passed to the class during the construction and at no time will this object ever created its own connection. Singletons become murky here since both are an acceptable approach as both are valid either within the class or passed into the class (since the end result is the same connection).

As for children, child classes will contain all members of their parent, even the private ones. The difference is that if the member is private, the child cannot directly access it. If the scope is modified to protected instead, then it will let you access it within a child. I'd suggest private member properties, and public (if warranted) or protected access methods instead, as that will prevent a child class from overwriting a parent member; however, PHP does not implicitly construct a parent object. If a child has overridden the __construct method, you must explicitly call parent::__construct(...) within the child. If the child has no reason to declare its own constructor, then a parent may mark that constructor as final to prevent the child from overriding it.

Oh, I should mention too, that even if you decide to construct an object as a composite from required data, there's nothing that says you cannot provide it with alternative at this level. For an example:
PHP Code:
class User
{
    private 
$storage;
    public function 
__construct(Storage $storage)
    {
          
$this->storage $storage;
    }
}

//. . .
$storage = new Storage(/* default config */);
$p = new NewsItem($storage);

$userStorage = new Storage(/* config from user */);
$u = new User($userStorage); 
Now, with the above if config is drawn from a location that User dictates as its config, then it is provided with an object during construction with the same config that User would otherwise have used during its construction.
There is a difference here though, and that difference is containment. User is no longer responsible for drawing its own storage, rather another class or main is responsible for constructing it based off of configurations that would be dictated by the User class. While this is valid code, I wouldn't do this myself as now you have a reliance created by the calling application to read the configuration that is controlled by the User class.
Does this make any sense? Its a bit on the complicated side, but I'm trying to say that anything controlled directly or sole responsibility of class User should be controlled immediately by class User and not controlled in any way by the primary application or main methods. Unfortunately without creating a mass of classes and relations in a UML this is very difficult to explain as to whether passing an object to a class during construction is better than constructing within the class itself.

If it helps you, for the most part of what I read your requirements are, I'd suggest that your classes using storage are more composite, so you should accept the Connection object into the class as a construction argument.
PHP Code:
class User
{
    private 
$con;
    public function 
__construct(Connection $con)
    {
        
$this->con $con;
    }
}

class 
NewsItem
{
    private 
$con;
    public function 
__construct(Connection $con)
    {
        
$this->con $con;
    }
}

//. . .
$con Connection::getInstance();
$user = new User($con);
$user->setuserid(1);
$user->load();

$ni = new NewsItem($con);
$ni->setUser($user);
$ni->setComment('This is an article');
$ni->save(); 
Is more how I perceive you are going. If you implement error handling within the Connection class itself, then you can guarantee that each of these are provided with a valid connection object.
Fou-Lu is offline   Reply With Quote
Users who have thanked Fou-Lu for this post:
Oatley (09-14-2012)
Old 09-14-2012, 09:33 PM   PM User | #7
Oatley
New Coder

 
Join Date: Sep 2012
Posts: 70
Thanks: 56
Thanked 0 Times in 0 Posts
Oatley is an unknown quantity at this point
Wow, that's an fantastic post. Thank you very much for the detailed reply. Really helps me a lot.
Oatley is offline   Reply With Quote
Reply

Bookmarks

Jump To Top of Thread


Thread Tools
Rate This Thread
Rate This Thread:

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT +1. The time now is 06:37 AM.


Advertisement
Log in to turn off these ads.