GLOBALS vs CONSTRUCT

  • Bogey
  • Genius
  • Genius
  • Bogey
  • Posts: 8416
  • Loc: USA

Post 3+ Months Ago

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...
  • joebert
  • Fart Bubbles
  • Genius
  • User avatar
  • Posts: 13504
  • Loc: Florida

Post 3+ Months Ago

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.
  • Bogey
  • Genius
  • Genius
  • Bogey
  • Posts: 8416
  • Loc: USA

Post 3+ Months Ago

How do I manage connections?
  • joebert
  • Fart Bubbles
  • Genius
  • User avatar
  • Posts: 13504
  • Loc: Florida

Post 3+ Months Ago

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.
  • Bogey
  • Genius
  • Genius
  • Bogey
  • Posts: 8416
  • Loc: USA

Post 3+ Months Ago

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'?
  • joebert
  • Fart Bubbles
  • Genius
  • User avatar
  • Posts: 13504
  • Loc: Florida

Post 3+ Months Ago

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.
  • Bogey
  • Genius
  • Genius
  • Bogey
  • Posts: 8416
  • Loc: USA

Post 3+ Months Ago

What if I make __construct private?

Another question: What is the difference between self::function() or $this->function()?
  • Nightslyr
  • Proficient
  • Proficient
  • Nightslyr
  • Posts: 283

Post 3+ Months Ago

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
  • Genius
  • Genius
  • Bogey
  • Posts: 8416
  • Loc: USA

Post 3+ Months Ago

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.
  • joebert
  • Fart Bubbles
  • Genius
  • User avatar
  • Posts: 13504
  • Loc: Florida

Post 3+ Months Ago

__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.
  • Bogey
  • Genius
  • Genius
  • Bogey
  • Posts: 8416
  • Loc: USA

Post 3+ Months Ago

Once again, the reason I made my __construct private is from this post. They didn't tell me not to do it :(
  • hexlat
  • Beginner
  • Beginner
  • hexlat
  • Posts: 38

Post 3+ Months Ago

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
  • hexlat
  • Posts: 38

Post 3+ Months Ago

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
  • Fart Bubbles
  • Genius
  • User avatar
  • Posts: 13504
  • Loc: Florida

Post 3+ Months Ago

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 ?
  • hexlat
  • Beginner
  • Beginner
  • hexlat
  • Posts: 38

Post 3+ Months Ago

I would hope the documentation would be easier to understand than a cryptic error.
  • Bogey
  • Genius
  • Genius
  • Bogey
  • Posts: 8416
  • Loc: USA

Post 3+ Months Ago

joebert wrote:
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.

Due to the nature of my class, I can't have a constructor function. What about the following alternative?
PHP Code: [ Select ]
<?php
function connect($dbname = 2)
{
   if(is_resource($this->mysql_link) || @mysql_ping($this->mysql_link))
   {
      return;
   }
   
   // 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->con_error);
   }
   
   // Selecting the Database
   $this->dbselect($dbname);
}
?>
  1. <?php
  2. function connect($dbname = 2)
  3. {
  4.    if(is_resource($this->mysql_link) || @mysql_ping($this->mysql_link))
  5.    {
  6.       return;
  7.    }
  8.    
  9.    // Connecting to MySQL
  10.    if($this->persistant)
  11.    {
  12.       // Persistant connect
  13.       $this->mysql_link = mysql_pconnect($this->host, $this->user, $this->pass) or mysql_error();
  14.    }
  15.    else
  16.    {
  17.       // Normal Connect
  18.       $this->mysql_link = mysql_connect($this->host, $this->user, $this->pass) or mysql_error();
  19.    }
  20.    
  21.    if(!is_resource($this->mysql_link))
  22.    {
  23.       die($this->con_error);
  24.    }
  25.    
  26.    // Selecting the Database
  27.    $this->dbselect($dbname);
  28. }
  29. ?>
Would that serve the same purpose?
  • hexlat
  • Beginner
  • Beginner
  • hexlat
  • Posts: 38

Post 3+ Months Ago

Bogey, I can explain to you the rationale behind a singleton class, but afterward please go out on the net, look up and understand the singleton class. You need to understand it before you can implement it.

The whole point behind the singleton class is instance control. It controls how many instances of this class are running in a particular process. It does this by denying public access to the constructor. This makes it so new can't be called by someone outside the class. It then exposes a function which a user can use to get a reference to an allocated object under its control (and possibly instantiate the instance if there is none). In the classic singleton pattern it allows only one instance object of the class.

So what you are missing is your allocation control function, because you still need to allocate the memory for your object.
  • Bogey
  • Genius
  • Genius
  • Bogey
  • Posts: 8416
  • Loc: USA

Post 3+ Months Ago

This post has nothing to do with singleton classes or anything... this post was a reply to the post I quoted.

Thanks for the explanation about the singleton classes anyway.
  • hexlat
  • Beginner
  • Beginner
  • hexlat
  • Posts: 38

Post 3+ Months Ago

Correct me if i am wrong but where you not trying to make your connect function act like a constructor or am I completely missing the mark?
  • Bogey
  • Genius
  • Genius
  • Bogey
  • Posts: 8416
  • Loc: USA

Post 3+ Months Ago

No, I wasn't. Joebert suggested that in his post, but that's not what I wanted. I'm making my connect function as a separate function. And this class isn't the singleton class. The singleton class thing came from ... well, me but I meant to post that somewhere else... and I did.
  • hexlat
  • Beginner
  • Beginner
  • hexlat
  • Posts: 38

Post 3+ Months Ago

Ahhh no wonder why I am totally confused.
  • joebert
  • Fart Bubbles
  • Genius
  • User avatar
  • Posts: 13504
  • Loc: Florida

Post 3+ Months Ago

You'll figure it out sooner or later, and when you do you'll know what I meant. :)
  • Bogey
  • Genius
  • Genius
  • Bogey
  • Posts: 8416
  • Loc: USA

Post 3+ Months Ago

joebert wrote:
You'll figure it out sooner or later, and when you do you'll know what I meant. :)

Who are you replying to and about what topic?

:lol: This thread covered three different topics :roll:
  • cjxxi
  • Expert
  • Expert
  • cjxxi
  • Posts: 566
  • Loc: Fort Worth, TX

Post 3+ Months Ago

I try not to write Globals, and I do like singleton, I use more static variables almost as much as regular variables.
And I use them for example for this scenario:


Code: [ Select ]
private static $getData = array();
public static function getData()
{
if(self::$getData) {
return self::$getData;
}
$sql = "get data from table";
$r = $db->getall($sql);

return self::$getData = $r;
}
  1. private static $getData = array();
  2. public static function getData()
  3. {
  4. if(self::$getData) {
  5. return self::$getData;
  6. }
  7. $sql = "get data from table";
  8. $r = $db->getall($sql);
  9. return self::$getData = $r;
  10. }


no matter how many times you call function getData(), it will only use the database once. what else do you need other than that?

no need for Globals, not that I have anything against Globals (ohh wait, maybe I do.. lol), It is just a habit not to use them.

And my friend Jonathan at Geodesic (I used to work for them), almost kills me when he found out I was trying to use Globals once!,
  • northstjarna
  • Beginner
  • Beginner
  • northstjarna
  • Posts: 58
  • Loc: Chertsey, UK

Post 3+ Months Ago

Hi there,

Just skimmed over this... Don't know if it's the best way...

I store my db connection in one file and do a require_once to include the file for each page.

My include file would look like this:
Code: [ Select ]

<?php

$application_name = "variable1";
$base_url = "http://www.someurl..."; // for ref to our site
$imageurl = $base_url . "/uploaded_images"; /// for image gallery
$basedir = "";
$modules = $base_url. "/editor/visual_editor/modules";

# FileName="Connection_php_mysql.htm"
# Type="MYSQL"
# HTTP="true"
$hostname = "localhost"; /* or"localhost"; */
$database = "db_" . $application_name;
$username = "etc";
$password = "pword";
$dbconnection = mysql_pconnect($hostname, $username, $password) or trigger_error(mysql_error(),E_USER_ERROR);

include('A_classes.php');

?>
  1. <?php
  2. $application_name = "variable1";
  3. $base_url = "http://www.someurl..."; // for ref to our site
  4. $imageurl = $base_url . "/uploaded_images"; /// for image gallery
  5. $basedir = "";
  6. $modules = $base_url. "/editor/visual_editor/modules";
  7. # FileName="Connection_php_mysql.htm"
  8. # Type="MYSQL"
  9. # HTTP="true"
  10. $hostname = "localhost"; /* or"localhost"; */
  11. $database = "db_" . $application_name;
  12. $username = "etc";
  13. $password = "pword";
  14. $dbconnection = mysql_pconnect($hostname, $username, $password) or trigger_error(mysql_error(),E_USER_ERROR);
  15. include('A_classes.php');
  16. ?>



don't know if that helps, but I would store all my global variables like that and then do an include or require at the top of an index page and my site is then using includes using template files and content.

Thanks

ANdi
  • Bogey
  • Genius
  • Genius
  • Bogey
  • Posts: 8416
  • Loc: USA

Post 3+ Months Ago

That's how I do it. Actually I have recommended that type of thing in a tutorial I wrote here some months ago.

The problem I am having is to prevent multiple connections to MySQL, although that shouldn't happen as I close my connections after I am done using it on each page... but mistakes happens and people forget and I want to be safe and sound :)
  • northstjarna
  • Beginner
  • Beginner
  • northstjarna
  • Posts: 58
  • Loc: Chertsey, UK

Post 3+ Months Ago

Yeah I close them too. An Alternative would to be to include a footer file on the index page to always close the connection. Then you would not have to worry about it coding it in every time?
  • Bogey
  • Genius
  • Genius
  • Bogey
  • Posts: 8416
  • Loc: USA

Post 3+ Months Ago

That's a quick and dirty work a-round. What I want is a clean and correct fix that makes the function work correctly. Right now, what I got I think works. I'm going to test it right now (I should have done that rather than asking here if it works :roll:) and tell you if it works :)
  • Bogey
  • Genius
  • Genius
  • Bogey
  • Posts: 8416
  • Loc: USA

Post 3+ Months Ago

joebert wrote:
You'll figure it out sooner or later, and when you do you'll know what I meant. :)

Could you please elaborate? I think I might know what you mean by 'figure it out', but there are so many things I have learned through this few days that it may be something entirely different.
  • Bogey
  • Genius
  • Genius
  • Bogey
  • Posts: 8416
  • Loc: USA

Post 3+ Months Ago

Alright... just tested and it works perfectly :D

Here is the test code:
PHP Code: [ Select ]
<?php
require "classes/db.php";
$db = new db;
 
echo 'Making the first Connection...<br />';
ob_flush();
flush();
ob_flush();
flush();
ob_flush();
flush();
sleep(1);
$db->connect();
echo $db->result . '<br /><br />';
ob_flush();
flush();
ob_flush();
flush();
ob_flush();
flush();
sleep(3);
echo 'Making the second connection...<br />';
ob_flush();
flush();
ob_flush();
flush();
ob_flush();
flush();
sleep(1);
$db->connect();
echo $db->result;
?>
  1. <?php
  2. require "classes/db.php";
  3. $db = new db;
  4.  
  5. echo 'Making the first Connection...<br />';
  6. ob_flush();
  7. flush();
  8. ob_flush();
  9. flush();
  10. ob_flush();
  11. flush();
  12. sleep(1);
  13. $db->connect();
  14. echo $db->result . '<br /><br />';
  15. ob_flush();
  16. flush();
  17. ob_flush();
  18. flush();
  19. ob_flush();
  20. flush();
  21. sleep(3);
  22. echo 'Making the second connection...<br />';
  23. ob_flush();
  24. flush();
  25. ob_flush();
  26. flush();
  27. ob_flush();
  28. flush();
  29. sleep(1);
  30. $db->connect();
  31. echo $db->result;
  32. ?>

And here is the connect(); function
PHP Code: [ Select ]
<?php
function connect()
{
   if(is_resource($this->mysql_link) || @mysql_ping($this->mysql_link))
   {
      $this->result = 'MySQL is already connected';
      return true;
   }
   
   // Connecting to MySQL
   if($this->persistant)
   {
      // Persistant connect
      $this->mysql_link = @mysql_pconnect($this->host, $this->user, $this->pass);
   }
   else
   {
      // Normal Connect
      $this->mysql_link = @mysql_connect($this->host, $this->user, $this->pass);
   }
   
   if(!is_resource($this->mysql_link))
   {
      die("The error here");
   }
   
   $this->result = 'Just now connected to MySQL';
}
?>
  1. <?php
  2. function connect()
  3. {
  4.    if(is_resource($this->mysql_link) || @mysql_ping($this->mysql_link))
  5.    {
  6.       $this->result = 'MySQL is already connected';
  7.       return true;
  8.    }
  9.    
  10.    // Connecting to MySQL
  11.    if($this->persistant)
  12.    {
  13.       // Persistant connect
  14.       $this->mysql_link = @mysql_pconnect($this->host, $this->user, $this->pass);
  15.    }
  16.    else
  17.    {
  18.       // Normal Connect
  19.       $this->mysql_link = @mysql_connect($this->host, $this->user, $this->pass);
  20.    }
  21.    
  22.    if(!is_resource($this->mysql_link))
  23.    {
  24.       die("The error here");
  25.    }
  26.    
  27.    $this->result = 'Just now connected to MySQL';
  28. }
  29. ?>
And the result I got was:
Quote:
Making the first Connection...
Just now connected to MySQL

Making the second connection...
MySQL is already connected

Post Information

  • Total Posts in this topic: 32 posts
  • Users browsing this forum: No registered users and 52 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
 
 

© 1998-2014. Ozzu® is a registered trademark of Unmelted, LLC.