Issues

ZF-2015: Global entry point for established connection

Description

It is very convinient to use one or two DB connections in whole application - in many different places, like models, controllers, etc. Currently you have to take care yourself to create a global entry point to the adapter you create (for example in bootstrap). As this is the case for 99% of applications using Db I was thinking about a standard solution. My proposal is:


    protected static $_defaultConnection = 'default';

    /**
    * Returns current name for default connection.
    * Also, the method can be used as a setter for current default.
    * @param string $name OPTIONAL
    */
    public static function defaultConnection($name = null)
    {
        if ($name !== null)
        {
            self::$_defaultConnection = $name;
        }
        
        return self::$_defaultConnection;
    }
    
    /** (...)
    * @param string $name OPTIONAL name of connection to register with Zend_Registry
    */ (...)
    public static function factory($adapter, $config = array(), $name = null)
    {
        if ($name === null)
        {
            $name = self::$_defaultConnection;
        }
        
        // current code of the method goes here...
        // (...)
        
        // register an adapter in global scope
        Zend_Registry::set('db.'.$name, $dbAdapter);
        return $dbAdapter;
    }

    /**
    * Checks if there is a connection by $name.
    * @param string $name Name of connection to check
    * @return bool
    */
    public static function hasConnection($name = null)
    {
        if ($name === null)
        {
            $name = self::$_defaultConnection;
        }
        
        return Zend_Registry::isRegistered('db.'.$name);
    }
    
    /**
    * Returns a database connection established previously with Zend_Db::factory().
    * @return Zend_Db_Adapter_Abstract
    * @throws Zend_Db_Exception
    */
    public static function getConnection($name = null)
    {
        if ($name === null)
        {
            $name = self::$_defaultConnection;
        }
        
        if (!self::hasConnection($name))
        {
            require_once 'Zend/Db/Exception.php';
            throw new Zend_Db_Exception("Connection $name does not exist, use Zend_Db::factory() to establish it.");
        }
        
        return Zend_Registry::get('db.'.$name);
    }

It would not break backward compatibility if Zend_Registry class exists. There could be a condition if (class_exists('Zend_Registry')) to avoid that.

Comments

I'm actually not too keen on adding this functionality to the framework code. Providing global-scope named database connections is trivial, as evidenced by the simplicity of the above implementation, using Zend_Registry or by other means (e.g., Service Locator pattern). Zend_Db can be extended or composed to provide these functions. If such extensions do not work because of a flaw in the class design, please let us know.

Darby - if zend framework is going to be RAD solution - it should have such a feature. If everybody using the framework has to extend it with all the same trivial code again and again - that's really pointless and zend framework is going to be nice set of poorely related tools, like PEAR, instead of real framework. I thought that with controller/model/view components the ZF direction was concreted, but maybe it did not. You should really think why Rails framework for Ruby is so appreciated.

I see what your point, but I do think that if we were to add such functionality it would be important that it truly is as easy to use as possible, maybe is initializable by configuration as well as code, and has no 'muddying' effect on the DB or Registry API's for use cases that don't need to continually reuse the same few connections. Basically, I like your idea but I would go farther. :) In any case, this won't be addressed in 1.5 since we'll need to think about it more, so I am closing it for now. Have you already made a proposal to the community on the DB or General list?

Bookkeeping. Assigning all issues to the person that ultimately closed them.