1

Would setting the $link to my database be one thing that I should use a GLOBAL scope for? In my setting of (lots of functions)...it seems as though having only one variable that is in the global scope would be wise.

I am currently using the functions to transfer it back and forth so that way I do not have it in the global scope. But it is a bit of a hindrance to my script.

Please advise.

Michael Petrotta
  • 59,888
  • 27
  • 145
  • 179
Matt
  • 37
  • 5
  • 1
    Singletons are just an overly elaborate workaround to have global variables. It's a nicer notation, if your application is strictly object-oriented. But it's sometimes not as senseful in scripting languages like PHP. http://stackoverflow.com/questions/365261/ok-global-variable-is-condemned-singleton-is-despised-whats-the-alternative – mario May 30 '10 at 00:38
  • 1
    Yes, do. Consider globals 'ok' when it is for READ ONLY value. I thought of it this second so consider it a not thought out bad idea but use it for food for thought. Remember, calling functions can have side effects and just bc i said it is ok it doesnt mean i dont try to avoid it. in my web app i only have one place to create connections and i dont even call it. I have my base class initialize it upon creation! (think threads, client connections and new db on each client/thread) –  May 30 '10 at 06:01
  • You have enough similar replies, so I'll just comment instead. I wouldn't say globals are categorically bad, they're mostly messy. The "*Globals are bad*" argument (re: PHP) stems from auto-globals, which used to be very common. (A mechanism that declares all CGI parameters as global variables.) Use globals, use goto, or whatever you need to get the job done, but do it thoughtfully. – nikc.org May 30 '10 at 07:46

6 Answers6

3

Your best way to accomplish this is by using a function as there already global.

function getDB()
{
   global $Database;
   Return $Database;
}

Then throughout you application use

getDB()->query(...)

Or if your just calling the resource then

mysql_query(...,getDB());
RobertPitt
  • 56,863
  • 21
  • 114
  • 161
  • 2
    indeed, using a function lets you change your mind later about how exactly the database is gotten (the inside of the function). – seanmonstar May 30 '10 at 00:21
  • However I do see that using a function instead of a Global variable would limit its usage... I could even use this to return $link after the db function is complete...that would definitely make some sort of sense – Matt May 30 '10 at 00:48
  • If your creating UNIQUE Variable names you could create 1 function or static class that you can call like so Global('Database'); and in this function you could global $arg1 and return it so function Global($var){global global $var;return $var;} so it will globalize what you the string you asked and then return. – RobertPitt May 30 '10 at 00:55
  • I think I may understand. So all in all, all that I am doing is returning the non-global variable, thereby passing it to the function. – Matt May 30 '10 at 01:05
  • Instead of taking up code all your doing is globalizing the variable once, ie the function instead of writing it everytime you need it to be in scope your calling the function thus saving code. personally i would use a static scope object. sort of Registry so you can go Registry::set('DB',$Database); and because this is a global you can do Registry::get('DB'); if you wish to see the code just ask ill post it in my thread! – RobertPitt May 30 '10 at 01:11
  • So a function which combines the worst aspects of both Singletons and Globals is the accepted answer... Wow... – ircmaxell May 30 '10 at 12:35
  • Yes, Depending on the project/ application if its not a very huge project then this is an Acceptable Answer, The person who asks the question may not fully understand the concepts of Registry/Singleton static methods and there for them answers are illogical to him, i gave him the best answer for his skill level. – RobertPitt May 30 '10 at 13:30
  • Using a static class member variable is faster than a function call, even though it's almost as bad as a global variable. However, you don't pollute your global namespace and you could always replace e.g. `Core::$db` with `Core::getDB()` if you need more than a simply variable access. – ThiefMaster Nov 02 '10 at 00:41
2

Personally, I think the database is one place where the Singleton pattern makes sense. Testing fanatics might disagree with me, but it makes so much sense to me in this instance.

$db = DB::get();
$db->query('select ...');
seanmonstar
  • 11,284
  • 2
  • 21
  • 26
1

Globals are very bad instead use the singleton pattern.

  <?php
  class Singleton
  {
      static private $instances = array();

      static public function getInstance($className)
      {
          if (!isset(self::$instances[$className])) {
              self::$instances[$className] = new $className();
         }
         return self::$instances[$className];
     }
 }
 require_once 'DB.php';
 $db = Singleton::getInstance('DB');
 $db->query("select * .......");
?>
streetparade
  • 32,000
  • 37
  • 101
  • 123
  • I cannot deny that I am confused by this... I am still new working with php and mysql...but would this require every function to initially call singleton and then continue to its normal function? – Matt May 30 '10 at 00:44
  • Please explain why Singleton::getInstance('DB')->query(...) is better suited than $global_db->query(...) for PHP. Are there any hidden advantages in your Singleton use; do you restrict access or something else unusual? – mario May 30 '10 at 00:51
  • 2
    Singletons are basically globals by another name. – Loren Pechtel May 30 '10 at 00:57
  • That would not help me to decide if I was going to use them – Matt May 30 '10 at 01:04
  • Singletons are just fancy globals. – Lotus Notes May 30 '10 at 01:55
  • 1
    Singletons are not just fancy globals. With a global, you'll need to instantiate a DB connection early so that you'll have access to the $db var all throughout the script. With a Singleton, you can "lazy load" both the class, and the DB. Only creating the connection when you need it. Not to mention, it's impossible to "accidentally" overwrite the global var. Plus, it's easy to see what `$db = Database::instance();` is, whereas `global $db;` would require you to hunt through the code to try to figure out what it really is (`$db` is a trivial case, imagine any other class)... – ircmaxell May 30 '10 at 05:28
  • Sorry, my hatred for singletons make me an ass. I instantly downvote every time i see it. Globals are 'bad' but more obvious then a singleton class which is 'bad' and dress as a normal or typical class. –  May 30 '10 at 06:07
0

You can always access globals inside functions when you really need them.

function use_that_link() {
    global $link;
    var_dump($link);
}

But passing it around is probably better practice, regardless. Just remember that any function that uses direct database access takes the database link as its first parameter, and you should be good to go. (OOP might offer you an even cleaner solution, but it sounds like you don't want to venture down that path at this point.)

Matchu
  • 83,922
  • 18
  • 153
  • 160
0

A more pragmatic approach: rudimentary namespacing

$GLOBALS['mydomain.com']['db'] = ...;

You can make a wrapper class for accessing and mutating your globals

Class Globals {

  private $domain = 'mydomain.com';

  function get($key)
  {
    return $GLOBALS[$this->domain][$key];
  }

  function set($key,$value)
  {
    $GLOBALS[$this->domain][$key] = $value;
  }

}
Zilverdistel
  • 1,571
  • 11
  • 10
  • Would this be to prevent XSS? – Matt May 30 '10 at 07:27
  • My main concern is avoiding conflicts in the global namespace, which may be introduced by including third-party code in your application. ps: I don't see where XSS issues might rise in this matter .. – Zilverdistel May 30 '10 at 07:39
-1
class Registry
{
    /*
        * @var array Holds all the main objects in an array a greater scope access
        * @access private
    */
    private static $objects = array();

    /**
        * Add's an object into the the global
        * @param string $name
        * @param string $object
        * @return bool
    */
    public static function add($name,$object)
    {
        self::$objects[$name] = $object;
        return true;
    }

    /*
        * Get's an object out of the registry
        * @param string $name
        * @return object on success, false on failure
    */  
    public static function get($name)
    {   if(isset(self::$objects[$name]))
        {
            return self::$objects[$name];
        }
        return false;
    }

    /**
        * Removes an object out of Registry (Hardly used)
        * @param string $name
        * @return bool
    */
    static function remove($name)
    {
        unset(self::$objects[$name]);
        return true;
    }

    /**
        * Checks if an object is stored within the registry
        * @param string $name
        * @return bool
    */
    static function is_set($name)
    {
        return isset(self::$objects[$name]);
    }
}`

The you can use like so.

require_once 'classes/registry.class.php';

require_once 'classes/database/pdo.class.php';
Registry::set('Database',new Database);

Then anywhere in your Application you can do like so:

function addPost(String $post,Int $id)
{
    $statement = Registry::get('Database')->prepare('INSERT INTO posts VALUES(:d,:p)');
    $statement->bindValue(':p',$id,PDO::PARAM_INT);
    $statement->bindValue(':p',$post);
}

This will give you a much Larger scope!

RobertPitt
  • 56,863
  • 21
  • 114
  • 161
  • You cant set String as Typhinting in PHP, expect you have a class String and a Class Int this code looks 50% as PHP and 50% as Java code. – streetparade May 30 '10 at 13:23
  • This method is perfectly fine for storing Object in a database and fetching then with a larger scope. i have deeply used this for larger project. not to worry. peace – RobertPitt May 30 '10 at 13:32