GLOBALS vs CONSTRUCT

  • Bogey
  • Bogey
  • Genius
  • User avatar
  • Joined: Jul 14, 2005
  • Posts: 8211
  • Loc: USA
  • Status: Offline

Post February 23rd, 2009, 9:42 pm

I got this problem some time ago... I already know a few positives and negatives of some, but I want some more review on this.

I used to use the following way to get objects to be used throughout the class...
PHP Code: [ Select ]
<?php
function __construct()
{
     $this->db = new db();
     $this->funcs = new funcs();
}
?>
  1. <?php
  2. function __construct()
  3. {
  4.      $this->db = new db();
  5.      $this->funcs = new funcs();
  6. }
  7. ?>

And now, I'm getting the hang of "global"...
PHP Code: [ Select ]
global $db, $funcs, $config;

The good thing about the first way, is that it is good throughout the whole class, while using the second way, I have to put that for every function that uses those objects.

These objects are instantiated in a global file so they would be available globally throughout the site since they are the one most used objects in the site, and I guess classes void all that.. unless I put global where they are used... or if I use the construct thing, but then, if I change the class name, I'll have to change the class name in all those other classes I instantiated the object in the construct function...
"Bring forth therefore fruits meet for repentance:" Matthew 3:8
  • Anonymous
  • Bot
  • No Avatar
  • Joined: 25 Feb 2008
  • Posts: ?
  • Loc: Ozzuland
  • Status: Online

Post February 23rd, 2009, 9:42 pm

  • joebert
  • Sledgehammer
  • Genius
  • No Avatar
  • Joined: Feb 10, 2004
  • Posts: 13455
  • Loc: Florida
  • Status: Offline

Post February 24th, 2009, 12:20 pm

You have to decide on a case-to-case basis which is better for each variable.

For instance,

Code: [ Select ]
$this->db = new db();


That's a disaster waiting to happen. Depending on how many classes you have doing that, and how many instances you have at a given time, you could potentially have a lot of database connections going at one time, even if you made $this->db static.

Since your PHP application executes syncroniously rather than asyncroniously, lots of database connections is a bad thing. :)

However many instances of funcs might not be a bad thing depending on what the funcs class does.

Multiple instances of db might not even be a bad thing if your db class manages the number of connections and makes sure there's never more than needed.
Strong with this one, the sudo is.
  • Bogey
  • Bogey
  • Genius
  • User avatar
  • Joined: Jul 14, 2005
  • Posts: 8211
  • Loc: USA
  • Status: Offline

Post February 24th, 2009, 2:33 pm

How do I manage connections?
"Bring forth therefore fruits meet for repentance:" Matthew 3:8
  • joebert
  • Sledgehammer
  • Genius
  • No Avatar
  • Joined: Feb 10, 2004
  • Posts: 13455
  • Loc: Florida
  • Status: Offline

Post February 24th, 2009, 3:07 pm

Your db class would have a static variable used to store the reference returned from mysqli_connect/etc, all instances would refer to that static variable, and your methods would ping the connection before use.
Strong with this one, the sudo is.
  • Bogey
  • Bogey
  • Genius
  • User avatar
  • Joined: Jul 14, 2005
  • Posts: 8211
  • Loc: USA
  • Status: Offline

Post February 24th, 2009, 3:10 pm

I use the following code to connect
Code: [ Select ]
<?php
// Connecting to MySQL
if($this->persistant)
{
    // Persistant connect
    $this->mysql_link = mysql_pconnect($this->host, $this->user, $this->pass) or mysql_error();
}
else
{
    // Normal Connect
    $this->mysql_link = mysql_connect($this->host, $this->user, $this->pass) or mysql_error();
}

if(!is_resource($this->mysql_link))
{
    die($this->mysql_link);
}
  1. <?php
  2. // Connecting to MySQL
  3. if($this->persistant)
  4. {
  5.     // Persistant connect
  6.     $this->mysql_link = mysql_pconnect($this->host, $this->user, $this->pass) or mysql_error();
  7. }
  8. else
  9. {
  10.     // Normal Connect
  11.     $this->mysql_link = mysql_connect($this->host, $this->user, $this->pass) or mysql_error();
  12. }
  13. if(!is_resource($this->mysql_link))
  14. {
  15.     die($this->mysql_link);
  16. }
Is that what you mean?

What do you mean by 'ping the connection before use'?
"Bring forth therefore fruits meet for repentance:" Matthew 3:8
  • joebert
  • Sledgehammer
  • Genius
  • No Avatar
  • Joined: Feb 10, 2004
  • Posts: 13455
  • Loc: Florida
  • Status: Offline

Post February 25th, 2009, 2:43 pm

http://www.php.net/manual/en/function.mysql-ping.php

Code: [ Select ]
class db
{
    private static $host = 'host', $user = 'user', $pass = 'pass';
 
    protected static $link;
    protected static function connect()
    {
        self::$link = mysql_connect(self::$host, self::$user, self::$pass);
    }
   
    public function __construct()
    {
        if( ! mysql_ping(self::$link))
        {
            self::connect();
        }
        return $this;
    }
   
    public function query($sql)
    {
        // work with $sql
    }
}
  1. class db
  2. {
  3.     private static $host = 'host', $user = 'user', $pass = 'pass';
  4.  
  5.     protected static $link;
  6.     protected static function connect()
  7.     {
  8.         self::$link = mysql_connect(self::$host, self::$user, self::$pass);
  9.     }
  10.    
  11.     public function __construct()
  12.     {
  13.         if( ! mysql_ping(self::$link))
  14.         {
  15.             self::connect();
  16.         }
  17.         return $this;
  18.     }
  19.    
  20.     public function query($sql)
  21.     {
  22.         // work with $sql
  23.     }
  24. }


I personally don't like singleton classes.
I like to think that the only things worth writing classes for are things that will be instanciated at least twice.
I think once namespaces in PHP mature classes like that will not be used in new code.
Strong with this one, the sudo is.
  • Bogey
  • Bogey
  • Genius
  • User avatar
  • Joined: Jul 14, 2005
  • Posts: 8211
  • Loc: USA
  • Status: Offline

Post March 13th, 2009, 10:08 am

What if I make __construct private?

Another question: What is the difference between self::function() or $this->function()?
"Bring forth therefore fruits meet for repentance:" Matthew 3:8
  • Nightslyr
  • Proficient
  • Proficient
  • No Avatar
  • Joined: Sep 21, 2005
  • Posts: 274
  • Status: Offline

Post March 13th, 2009, 11:12 am

Bogey wrote:
What if I make __construct private?

Another question: What is the difference between self::function() or $this->function()?


'self' is used to reference the class that the static member resides in. 'this' is used to represent the member of an individual object.

So, 'self' = class-wide self-reference (used with static). 'this' = individual object's self-reference.

Also, globals are bad. They can be overwritten accidentally, and can make maintaining code more difficult in the long run. If you absolutely think you need global scope for some things, stick them in a Singleton. At least you'll be keeping some sort of encapsulation in place.
  • Bogey
  • Bogey
  • Genius
  • User avatar
  • Joined: Jul 14, 2005
  • Posts: 8211
  • Loc: USA
  • Status: Offline

Post March 13th, 2009, 11:40 am

I am making a singleton class... that is why I am asking about making the __construct private for the database class and if I would need the mysql_ping in this case.
"Bring forth therefore fruits meet for repentance:" Matthew 3:8
  • joebert
  • Sledgehammer
  • Genius
  • No Avatar
  • Joined: Feb 10, 2004
  • Posts: 13455
  • Loc: Florida
  • Status: Offline

Post March 13th, 2009, 4:00 pm

__construct should always be defined as a public method.

global is not bad, you should only be using the keyword "global" when you're already aware of the variable in the global scope and you need access to it.

If you're overwriting variables using global accidently you're a hacker, not a programmer.
Strong with this one, the sudo is.
  • Bogey
  • Bogey
  • Genius
  • User avatar
  • Joined: Jul 14, 2005
  • Posts: 8211
  • Loc: USA
  • Status: Offline

Post March 13th, 2009, 9:06 pm

Once again, the reason I made my __construct private is from this post. They didn't tell me not to do it :(
"Bring forth therefore fruits meet for repentance:" Matthew 3:8
  • hexlat
  • Beginner
  • Beginner
  • No Avatar
  • Joined: Mar 20, 2009
  • Posts: 38
  • Status: Offline

Post March 20th, 2009, 6:39 pm

The real question here is about abstraction (bear with me here it will make sense). A singleton class or a global variable are both in the same global scope. What a singleton class provides is an abstraction for use.

For example:

No abstraction:
Take an integer variable, this is as basic as you can get, with no abstraction. You are able to directly edit this integer and do whatever arithmetic operations on it.

Function abstraction:
To abstract this requires controlling access to the variable and this is done by using functions/sub routine/methods. If this global variable was the constantly updated with the outside temperature you could provide getDegreesCentegrade() and getDegressFarienheit() functions. This would comprise your the interface to this variable.

Class abstraction:
Classes come into the picture when you want to control access to the data and group related functions and data together in a cohesive unit. This gives you the advantage of declaring your temperature variable private and provide methods to modify the variable. Perhaps a readOutsideTemperature() method. Granted this readOutsideTemperature() method could be a function, and then not make a class, but the downside would be that someone could still edit the temperature variable.


So the argument for the singleton class would be that it would allow you to provide a higher level of abstraction over using a global variable. However this can get tricky:

Code: [ Select ]
$db = new DatabaseConnection();


then later in a function:

Code: [ Select ]
function commit() {
   global $db;
 
   $db->doStuff();
}
  1. function commit() {
  2.    global $db;
  3.  
  4.    $db->doStuff();
  5. }


would be (mostly) equal to the singleton solution:

Code: [ Select ]
function commit() {
   $db = DatabaseConnection::getInstance();
   $db->doStuff();
}
  1. function commit() {
  2.    $db = DatabaseConnection::getInstance();
  3.    $db->doStuff();
  4. }


They both provide equal abstraction and they are pretty much equal. The only difference is that in the global method someone can muck around with the $db variable in a function and produce a side effect. This is usually a bad thing. The only reason I can see for doing that would be to change what $db references thus changing the database connection. Changing the database connection should most likely be some service the abstraction layer provides.

In general you want to avoid global variables, however if you can come up with a good reason you can use them. However please use caution; they can bite you in unexpected ways.
  • hexlat
  • Beginner
  • Beginner
  • No Avatar
  • Joined: Mar 20, 2009
  • Posts: 38
  • Status: Offline

Post March 20th, 2009, 6:52 pm

As to the constructor in a singleton. It must be protected or private. This way the new operation can't be directly called on the object. The object must be allocated by a controlling static method usually something called like getInstance(). A protected constructor allows sub-classes while a private one would bar this from happening.
  • joebert
  • Sledgehammer
  • Genius
  • No Avatar
  • Joined: Feb 10, 2004
  • Posts: 13455
  • Loc: Florida
  • Status: Offline

Post March 21st, 2009, 1:49 am

Code: [ Select ]
Fatal error: Call to private strange::__construct() from invalid context in /www/test.php on line 24


What's easier to understand, the freaking documentation that explains it's a singleton class that you should have read before using it anyway, or that odd-ball error message ?
Strong with this one, the sudo is.
  • hexlat
  • Beginner
  • Beginner
  • No Avatar
  • Joined: Mar 20, 2009
  • Posts: 38
  • Status: Offline

Post March 23rd, 2009, 10:14 am

I would hope the documentation would be easier to understand than a cryptic error.
  • Anonymous
  • Bot
  • No Avatar
  • Joined: 25 Feb 2008
  • Posts: ?
  • Loc: Ozzuland
  • Status: Online

Post March 23rd, 2009, 10:14 am

Post Information

  • Total Posts in this topic: 32 posts
  • Users browsing this forum: No registered users and 178 guests
  • You cannot post new topics in this forum
  • You cannot reply to topics in this forum
  • You cannot edit your posts in this forum
  • You cannot delete your posts in this forum
  • You cannot post attachments in this forum
 
cron
 

© 2011 Unmelted, LLC. Ozzu® is a registered trademark of Unmelted, LLC.