+2  A: 

I generally choose options 4 and 5. If you write a sane autoloader, you should be able to either grab a singleton from an 'important' class or use a static function from one.

The choice between using a singleton instance or using static functions depends on the object. Database objects typically require a connection, so it's best to use a singleton (so you can use the same connection link with multiple calls)

For objects that just set/retrieve data, say .. a Session class, it may be best to use static functions (but mileage can easily vary here).

Either way, I would avoid globals if possible. Most of the time an autoloader can negate the need for them.

In reply to:

Can you expand on your use of the autoloader?

In a php file that is called on each request, define a simple autoloader using SPL or older syntax:

function __autoload($class) {
  $file = 'lib/' . $class . '.class.php';
  if (file_exists($file)) {
 require($file);
  }
}

So, in a lib folder, you could define your DB class in a file called DB.class.php

Then, in your code, if you called: $db = DB::getInstance();

The autoloader would automatically require() the DB.class.php file.

If you're not familiar with autoloaders, you can read about them here

Matt
+3  A: 

Except for your number 2, your proposals are actually all more or less number 1 in disguise. Number 4, for example, might be written as

class DB {

    static $connection;

    static function setConnection($cnx) {
        self::$connection = $cnx;
    }

    static function getConnection() {
        return self::$connection;
    }
}

which is, in fact, nothing but a fancy wrapper around a global variable. Your approach number 3 may have benefits, because it decouples the implementation (class/variable/whatsoever) and the consuming parts of the application.

$db = Registry::get("database/read-connection");

instead of getting the database from some compile-time defined code artifact (class like above, global variable), a fact, which will make it more friendly to dependency-injection mechanisms and configuration. Nonetheless, the name/value pairs contained in such a registry are nothing but global variables.

The only aesthetical solution I see would be number 2; it is the only "honest" solution not requiring some kind of globally shared state. And of course, facing all the difficulties you mention.

However... Borrowing the "practicality beats purity" moto from the Python zen, I'd actually go for 1 or 4/5: many of the disadvantages of global variables simply don't apply due to PHP's processing model (for example, anything related to thread-unsafety is simply not an issue with PHP). I would consider the registry model only, if there are actual requirements which mandate that kind of abstraction (for example, differing database connections to be used during a single run of the script depending on the context, advanced requirements with respect to configuration management, etc.)

Dirk
philfreo
@philfreo: Yes. It is the "path of least resistance". If you are not sure about the future direction of the development, do something similar to #3 or #4 or use global wrapper functions to access the variables in #1. This makes it possible to change to actual implementation later (say, if a registry becomes a requirement), without disturbing existing code too much.
Dirk
A: 

I think that to a large extent the key is simply to use some method consistently, and (although less crucial in the case of your option 2) to have consistent naming conventions that make it obvious which variables are globals. In short, this is a case where it's good to form a more restrictive "local dialect" of a computer language, but there may not be much to favor one of these dialects over another.

Far too often I've seen bodies of code where you can't tell what is a global and what is not, and there are no set of conventions you can learn that will make the task easier. (Almost inevitably in those cases, the comments come up equally short: nothing in the header comment of the function in question to clue you that it relies on global variables.)

Joe Mabel
+1  A: 

I approach this problem in a slightly different fashion in my personal framework, I will assume that you're using the Front Controller Pattern (normally this would be your index.php file).

I have a base class with that uses the __get() magic method to include and instantiate other sub classes, I also have a base function that acts as a singleton for the base class, something like this:

class Base
{
    public function __get($key)
    {
        if (is_file('./libraries/' . $key . '.php') === true)
        {
            $class = __CLASS__ . '_' . $key;

            if (class_exists($class, false) === false)
            {
                require('./libraries/' . $key . '.php');
            }

            return $this->$key = new $class();
        }
    }
}

function Base()
{
    static $result = null;

    if (is_null($result) === true)
    {
        $result = new Base();
    }

    return $result;
}

Since we are using the Front Controller Pattern it's safe to assume that the Base() function will always be there for us, so by writing something like:

Base()->DB->Query('SELECT * FROM users WHERE id = ' . Base()->CurrentUser->id);

It will always work, it really doesn't matter if you're calling that piece of code from the index.php file, from a View, a Model, a Controller or other library.

One really good thing about this method is that you can extend it to subclasses, one disadvantage though is not being able to have more than one instance (hence this function acting as a Singleton) of your classes, but you can hack it by doing some magic with the __set() method, if you really want to. __autoload() and good file naming conventions may help you to archive the same effect.

I'm not sure if this is a good approach to follow but I've been using it for a while and it works for me.

Alix Axel
What you basically is that you have a giant container class which all your calls pass through. I see this as very bad practice. What especially sets me off is that you said that you might use it from a "from a View, a Model, a Controller" - A class like this should in my opinion never be used in views and controllers, but only in model classes.
phidah
@phidah: Do you mind explaining why do you see this as such a bad practice? Also why do you say controllers / views shouldn't use it?
Alix Axel
@Alix Axel, I believe he's concerned about that because there should be no case where your view is accessing the database - it kind of eliminates the purpose of MVC to begin with.
philfreo
@philfreo: It allows you to do that but it doesn't mean you should actually do that. Also check the comments on this answer: http://stackoverflow.com/questions/1948686/what-are-your-templating-strategies/1948747#1948747 and this question: http://stackoverflow.com/questions/1973221/can-i-call-a-model-from-a-view
Alix Axel
@Alix Axel, I think you misunderstood me. I wasn't saying a View should never call a model, I was saying in MVC a View shouldn't be making direct SQL database calls.
philfreo
@philfreo: I understood you perfectly, my point is just because you *can* execute a direct SQL query from your view / whatever doesn't mean you *should*. This gives you total freedom but the call is up to you. Similarly, you *could* also use the mysql_* functions from your views if you wanted to, right?
Alix Axel
+7  A: 

As other people have said, there is no perfect solution to this. Somehow as a programmer I think that most of the methods you mention are somewhat 'dirty'.

Despite that I really like the dependency injection (more info here) pattern, which probably is closest to your #3.

Another benefit is that it offers configuration flexibility because alternative implementations of a given service can be used without recompiling code. This is useful in unit testing because it is easy to inject a fake implementation of a service into the object being tested by changing the configuration file. One drawback is that excessive or inappropriate use of dependency injection can make applications more complicated, harder to understand and more difficult to modify. Code that uses dependency injection can seem magical to some developers, since instantiation and initialization of objects is handled completely separately from the code that uses it. This separation can also result in problems that are hard to diagnose.

(from the Wikipedia article cited above)

phidah
Although it takes a little shift in thinking, DI is a very clean and efficient way to implement pattern #2. I find that using setters rather than constructor arguments to pass the dependencies is an easier pattern to scale (re your "now I need a logger" concern). It is also much easier to unit test than a magic global factory or singleton approach. You can inject mock or stub objects during testing to trigger behavior or test expected interface usage.
bd808
I second *dependency injection* for the same reasons, mainly for the benefits of unit testing and more strongly typed constructors (if you perhaps used constructor injection).
cballou
+1  A: 

I worked on a class called Zend_Registry, which is included in the Zend Framework, but the Registry can be used standalone too.

As you say, a Registry is simply a singleton class that serves as a key/value store for objects, but Zend_Registry can also be instantiated. So you can carry an object instance of a Registry around, or use it within other classes as a generic collection mechanism.

You can even store a Registry instance as an object value in the singleton registry, allowing for multi-level registries!

This class is simple, but it seems to solve a lot of the need for managing the need to have some objects accessible application-wide.

Bill Karwin
+1  A: 

Use Option 2 (the only pure one free of global things) and make it convenient enough through use of dependency injection.

Waquo
+1  A: 

I would certainly pass the DB in constructors. For logging, I might go the Singleton route and it would be the only occasion when I use a singleton. But definitely, I would pass the dependencies or rely on a dependency injection framework and containers.

For reference:

Gregory Pakosz
A: 

I Also recommand to use a thread-safe, Lazy Singleton class like

/// <summary>
    /// This is a thread-safe, lazy singleton.
    /// </summary>
    public static DataBaseManager Instance
    {
        get {
            Hajloo.DBManager.Instance.ManageActivation();
            return Nested.DataBaseManager;
        }
    }

/// <summary>
    /// Assists with ensuring thread-safe, lazy singleton
    /// </summary>
    private class Nested
    {
        static Nested() { }
        internal static readonly DataBaseManager dbManager = new DataBaseManager();
    }

with this patter you can have many usefull method on the class and use it, and causeit is lazy singleton, when ever the first request arrived, it will create aninstanse (new DataBaseManager() ) and it is available for upcoming requests

Nasser Hadjloo
A: 

Create a class called 'Context', which holds all the things you want to be global from the point of view of the code need logging and essential services - but it's not global from the point of code which sets up the Context.

Context is not a static class or a singleton, it is just an instance class. Pass Context in to constructors for classes that need it, instead of passing a zillion parameters.

Like singletons and statics it can be your gateway to all those necessaries, but it can also solve problems where you need to desingleton-ize.

Tim Lovell-Smith
Hm, anyone want to say why they downvoted this?
Tim Lovell-Smith
Another downvote and no comments? C'mon guys, teach me something.
Tim Lovell-Smith