SitePoint Sponsor

User Tag List

Results 1 to 18 of 18
  1. #1
    SitePoint Enthusiast
    Join Date
    Mar 2005
    Posts
    64
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    question about using a db connection as a global value

    I know I do a lot of things that aren't considered good practice but I have a job to do and often find that if I'm the only one working on it, speed wins every time.

    I could see people thinking that there is a problem with the following code (the global $db_web)but I honestly don't think that there is because it allows centralization of the connection. Is there something I'm missing?

    $db_web will be opened in the page usually via an include.

    class Content{

    public function getContent()
    {
    global $db_web;

    $sql="select headline, body from article where id=" . $id;

    $result=$db_web->query($sql)....

    }

    }

  2. #2
    SitePoint Evangelist ghurtado's Avatar
    Join Date
    Sep 2003
    Location
    Wixom, Michigan
    Posts
    591
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    The problem will appear once you face the need to use more than one connection object in your application (not that uncommon, for example, to use different databases) or the day that you need to integrate your application with another library that has made the same decisions about using global variable scope.

    Testing also becomes harder, since you will need to provide a different connection object in most cases, and finally, your class is not self-suficient in that it depends on a global object, and it depends on it to be named exactly "$db_web"; in short, your class is fully dependant on whatever include you use to define the global variable.
    Garcia

  3. #3
    ********* Victim lastcraft's Avatar
    Join Date
    Apr 2003
    Location
    London
    Posts
    2,423
    Mentioned
    2 Post(s)
    Tagged
    0 Thread(s)
    Hi...

    Quote Originally Posted by river_jetties
    Is there something I'm missing?
    Have you tried creating the connection in the top level script and simply passing it into the objects that need it. You may find it a lot easier than you think.

    Also can you describe your other development processes? You say you are the only person. Do you reuse your own libraries? Are you hit and run coding where you never touch the scripts again, or do you have to maintain them over time?

    The forces you describe are usually symtoms of bigger problems. By tackling these you may find you go a lot quicker.

    yours, Marcus
    Marcus Baker
    Testing: SimpleTest, Cgreen, Fakemail
    Other: Phemto dependency injector
    Books: PHP in Action, 97 things

  4. #4
    SitePoint Enthusiast
    Join Date
    Oct 2003
    Location
    norway
    Posts
    92
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by ghurtado
    The problem will appear once you face the need to use more than one connection object in your application (not that uncommon, for example, to use different databases) or the day that you need to integrate your application with another library that has made the same decisions about using global variable scope
    Although true, this is a moot point for me. I've developed websolutions for years and rarely have to use more than one connection, which then works out fine, and never had any integration problems. In larger-scale applications, this becomes more apparent, but then you would hopefully already know this.. Never have I had to change a database either, so using mysql_* against everybodys advice has worked out just fine. And then you don't even need a global handler (just remember to only use 1 handler)..

    I'm not doing it like this anymore (the global keyword gives me the willies), I'm just saying in my experience, for solo-developers, this really works better than what some try to convince you. It's a terrible way to develop systems and your own skills, but it works. There's a reason PHP is so popular; it's ridiculously easy.

  5. #5
    simple tester McGruff's Avatar
    Join Date
    Sep 2003
    Location
    Glasgow
    Posts
    1,690
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Php is desperate to make connections global even if you don't pass a global var around. A mysql_connect call will just use an open connection if no connection parameter is used. Also if you make a second call to mysql_connect with the same parameters, you get the previous connection - unless you set the optional new link parameter to true, ie:

    PHP Code:
        class MysqlDatabase
        
    {
            function 
    MysqlDatabase($host$user$pass)
            {
                
    $this->_connection mysql_connect($host$user$passtrue);
           
        
    // etc 
    The trouble with code that "just works" is that it invariably doesn't when exposed to serious challenges. It's imperative that a Database object should encapsulate the state associated with a particular connection (currently used db, errors, etc). You can get away with it for a while but wires will get crossed somewhere along the line - (unit) testing in particular will expose these flaws.

  6. #6
    eschew sesquipedalians silver trophy sweatje's Avatar
    Join Date
    Jun 2003
    Location
    Iowa, USA
    Posts
    3,749
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I know of one developer who defines a constant DB equal to the resource returned from the mysql_connect, and then uses that define in conjunction with mysql_* functions. Clearly there are no effective means of testing this setup, and no abstraction at all (say for changing to a different database), but it was an interesting means of providing a GLOBAL resource.
    Jason Sweat ZCE - jsweat_php@yahoo.com
    Book: PHP Patterns
    Good Stuff: SimpleTest PHPUnit FireFox ADOdb YUI
    Detestable (adjective): software that isn't testable.

  7. #7
    SitePoint Member
    Join Date
    Jul 2005
    Posts
    24
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    well tons of older code use this approach, and if your lucky enough that the global variable doesn't get changed somehow then this _will_ work although yes it may bring a lot of difficulties in the future but for just simple enough scripts i think this approach is just fine especally for really small scale projects.

    a lot of open source projects use this approach AFAIK.

  8. #8
    SitePoint Zealot
    Join Date
    Mar 2005
    Posts
    116
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    A simple alternative to using global variables throughout code is just to create a function that returns the database connection. The connection can remain global, but you now have a single point of access for entire app:

    function getConnection() {
    global $db;
    return $db;
    }

    This way your code won't need to decalre the global at every turn.

    Later on, if you ever need to use multiple connections, you can refactor this function to take some form of identifier, and you could also set up some smarts to create the connection on demand. If you are really excited (or rather, misguided) you could make it a singleton pattern but there really is no point.

  9. #9
    SitePoint Wizard silver trophy kyberfabrikken's Avatar
    Join Date
    Jun 2004
    Location
    Copenhagen, Denmark
    Posts
    6,157
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by sweatje
    I know of one developer who defines a constant DB equal to the resource returned from the mysql_connect, and then uses that define in conjunction with mysql_* functions. Clearly there are no effective means of testing this setup, and no abstraction at all (say for changing to a different database), but it was an interesting means of providing a GLOBAL resource.
    ...

    What is the difference between that, and simply not passing the connection-id to the mysql_* functions ? (Which is optional anyway)

  10. #10
    eschew sesquipedalians silver trophy sweatje's Avatar
    Join Date
    Jun 2003
    Location
    Iowa, USA
    Posts
    3,749
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by kyberfabrikken
    What is the difference between that, and simply not passing the connection-id to the mysql_* functions ? (Which is optional anyway)
    Not sure, again was not something I do, just something I heard about. I suppose you could easily provide multiple db connections, say DB and DB_LOG or whatever.

    What was more interesting to me was the thought of defining a constant to refer to a resource. You could probably do the same for an open log file handle, etc.

  11. #11
    SitePoint Wizard silver trophy kyberfabrikken's Avatar
    Join Date
    Jun 2004
    Location
    Copenhagen, Denmark
    Posts
    6,157
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by sweatje
    What was more interesting to me was the thought of defining a constant to refer to a resource. You could probably do the same for an open log file handle, etc.
    I remeber seing a script, where STDIN was defined from fopen(). That's the same reasoning I suppose.

  12. #12
    eschew sesquipedalians silver trophy sweatje's Avatar
    Join Date
    Jun 2003
    Location
    Iowa, USA
    Posts
    3,749
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by kyberfabrikken
    I remeber seing a script, where STDIN was defined from fopen(). That's the same reasoning I suppose.
    IIRC, there is always a STDIN constant for the CLI version of PHP5, perhaps they were emulating this in PHP4?

  13. #13
    SitePoint Wizard silver trophy kyberfabrikken's Avatar
    Join Date
    Jun 2004
    Location
    Copenhagen, Denmark
    Posts
    6,157
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by sweatje
    IIRC, there is always a STDIN constant for the CLI version of PHP5, perhaps they were emulating this in PHP4?
    Likely so.

  14. #14
    SitePoint Wizard stereofrog's Avatar
    Join Date
    Apr 2004
    Location
    germany
    Posts
    4,324
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by sweatje
    What was more interesting to me was the thought of defining a constant to refer to a resource. You could probably do the same for an open log file handle, etc.
    Honestly, I don't think it's an excellent idea. First, assigning resources to constants is at least undocumented, if not unreliable (you know, they love changes).
    Quote Originally Posted by manual
    Only scalar data (boolean, integer, float and string) can be contained in constants.
    Second, define'd resource isn't really a readonly (constant) object. Consider
    PHP Code:
    define('LOG_FILE'fopen("log""a")); 
    What prevents someone from saying
    PHP Code:
    fclose(LOG_FILE); // oops 

  15. #15
    eschew sesquipedalians silver trophy sweatje's Avatar
    Join Date
    Jun 2003
    Location
    Iowa, USA
    Posts
    3,749
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by stereofrog
    Honestly, I don't think it's an excellent idea. First, assigning resources to constants is at least undocumented, if not unreliable (you know, they love changes).
    I agree. I only thought it was interesting, not nescesarily good

  16. #16
    SitePoint Guru OfficeOfTheLaw's Avatar
    Join Date
    Apr 2004
    Location
    Quincy
    Posts
    636
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by tobyhede
    A simple alternative to using global variables throughout code is just to create a function that returns the database connection. The connection can remain global, but you now have a single point of access for entire app:

    function getConnection() {
    global $db;
    return $db;
    }

    This way your code won't need to decalre the global at every turn.

    Later on, if you ever need to use multiple connections, you can refactor this function to take some form of identifier, and you could also set up some smarts to create the connection on demand. If you are really excited (or rather, misguided) you could make it a singleton pattern but there really is no point.

    You're halfway to using a singleton, why not go all the way (or, at least part of the way)?

    PHP Code:
    /**
     * Method to return an instance of an adodb connection
     */
    function &getConnection()
      {
      static 
    $conn = Array();
      
      if(empty(
    $conn))
        {
        
    $conn[0] = &ADONewConnection(DB_TYPE); # eg 'mysql' or 'postgres'
        
    $conn[0]->Connect(DB_SERVERDB_USERDB_PASSWORDDB_DATABASE);
        
    $conn[0]->setFetchMode(ADODB_FETCH_ASSOC);
        } 
      return 
    $conn[0];
      } 
    And all you do to get the connection:
    PHP Code:
    $db_web = &getConnection(); 
    What's so difficult about that, to me it seems fairly simple and not only avoids using globals, but ensures the state of the reference returned. Okay, there really is nothing to keep someone from closing the connection in this example, but you could wasly add another conditional to check if it has been closed, and if it has, re-connect.

    Alot better than using a global... I've seen cases where globals were used exclusively in a large app, and somewhere someone decided to use the variable $db for something else in the global scope, which now effectlively breaks all your code.

    In fact, I'd say it requires more work to use a global var, because then if you want your code to be solid you'll need to check it each and every time before you use it to make sure it hasn't been unset. Kinda messy

    James Carr, Software Engineer


    assertEquals(newXPJob, you.ask(officeOfTheLaw));

  17. #17
    SitePoint Wizard
    Join Date
    Aug 2004
    Location
    California
    Posts
    1,672
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I find that if I pass the connection through I have more control on when or whether it is instansiated. If it is global I am assuming that is is always created. I often have sections of a site that just assemble HTML templates. I don't have that controller create a connection because it is not needed.

    Usually I use something like:
    PHP Code:
    class Content{

    public function 
    Content($db) {
        
    $this->db $db;
    }

    public function 
    getContent($id) {
        
    $sql="select headline, body from article where id=" $id;
        
    $result=$this->db->query($sql)....
    }


    Christopher

  18. #18
    SitePoint Addict timvw's Avatar
    Join Date
    Jan 2005
    Location
    Belgium
    Posts
    354
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Well, and i have something in between

    My base Model class accepts a DAO instance (db+table specification/connection) in the constructor.. Usually all the classes that extend/inherit have the following call in their constructor:

    PHP Code:
    function SomeModel extends Model
    {
      function 
    SomeModel()
      {
        
    $dao =& Configuration::getDAO('somemodel');
        
    parent::Model($dao);
      }

    and configuation would than be something like officethelaw posted.. Except that it accepts a "name" to choose which specif db/table should be returned


Bookmarks

Posting Permissions

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