Hello and welcome to our community! Is this your first visit?
Register
Enjoy an ad free experience by logging in. Not a member yet? Register.
Results 1 to 7 of 7
  1. #1
    New Coder
    Join Date
    Sep 2012
    Posts
    76
    Thanks
    61
    Thanked 0 Times in 0 Posts

    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

  • #2
    God Emperor Fou-Lu's Avatar
    Join Date
    Sep 2002
    Location
    Saskatoon, Saskatchewan
    Posts
    16,978
    Thanks
    4
    Thanked 2,659 Times in 2,628 Posts
    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.

  • Users who have thanked Fou-Lu for this post:

    Oatley (09-14-2012)

  • #3
    New Coder
    Join Date
    Sep 2012
    Posts
    76
    Thanks
    61
    Thanked 0 Times in 0 Posts
    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:

    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.

    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.

    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

  • #4
    God Emperor Fou-Lu's Avatar
    Join Date
    Sep 2002
    Location
    Saskatoon, Saskatchewan
    Posts
    16,978
    Thanks
    4
    Thanked 2,659 Times in 2,628 Posts
    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.

  • Users who have thanked Fou-Lu for this post:

    Oatley (09-14-2012)

  • #5
    New Coder
    Join Date
    Sep 2012
    Posts
    76
    Thanks
    61
    Thanked 0 Times in 0 Posts
    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

    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.

  • #6
    God Emperor Fou-Lu's Avatar
    Join Date
    Sep 2002
    Location
    Saskatoon, Saskatchewan
    Posts
    16,978
    Thanks
    4
    Thanked 2,659 Times in 2,628 Posts
    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.

  • Users who have thanked Fou-Lu for this post:

    Oatley (09-14-2012)

  • #7
    New Coder
    Join Date
    Sep 2012
    Posts
    76
    Thanks
    61
    Thanked 0 Times in 0 Posts
    Wow, that's an fantastic post. Thank you very much for the detailed reply. Really helps me a lot.


  •  

    Posting Permissions

    • You may not post new threads
    • You may not post replies
    • You may not post attachments
    • You may not edit your posts
    •