views:

139

answers:

4

I have a Zend_Framework application, which has a whole bunch of model classes.

I need these model classes to be able to access the application's database (naturally).

Currently I've put this in my index.php:

Zend_Registry::set('db',
        $application->bootstrap()->getBootstrap()
        ->getPluginResource('db')->getDbAdapter());

And then $db = Zend_Registry::get('db'); in each of my model classes that require the database.

But this seems like a horrible horrible hack. Am I missing something basic here?

+2  A: 

Example of setting up SQLITE in your application.ini. You can also setup for MySQL or others.

resources.db.adapter = "PDO_SQLITE"
resources.db.params.dbname = APPLICATION_PATH "/../data/db/guestbook.db"

Once the db is loaded into the application you may extend the Zend_Db_Table_Abstract

class Application_Model_DbTable_Guestbook extends Zend_Db_Table_Abstract
{
    /** Table name */ 
    protected $_name    = 'guestbook';

    public function init() {
        $db = $this->getAdapter();

    }
}

You can use the zend methods...

        $select = $db->select()
         ->from(array('p' => 'products'),
                array('product_id', 'product_name'))
         ->join(array('l' => 'line_items'),
                'p.product_id = l.product_id');

Or you can do straight sql...

$sql = 'SELECT * FROM table1 t1 JOIN table2 t2 ON (t1.id = t2.id) JOIN table3 t3 ON (t3.id = t2.id);
$db->query($sql)->fetchAll(); 

All of this can be done in any model class that extends the Zend_Db_Table_Abstract

Brant
Yes, I can setup the database in the application settings. But there's no obvious way to get the database object into a model.
Billy ONeal
@Billy - Take a look again.
Brant
I do not want to use a table data gateway. It's difficult to represent datasets which routinely require joining 5 or 6 tables with that pattern.
Billy ONeal
@Billy - Everything you're trying to do can be done in your model class. You're going to have to do more research. http://framework.zend.com/manual/en/zend.db.select.html
Brant
Ha! Seeing your edit sort of makes me laugh -- obviously that's a roundabout solution to grabbing the DB adapter! I'd +1 again but I can't hehe.
Billy ONeal
@Billy - It's all good! Hope this works out for you.
Brant
+1  A: 

EDIT

Since you don't want to implement Zend_Db_Table_Abstract you could extend your current model to on __construct preform the Zend_Registry::get('db') and then store it to $this->db.

Then in all your models you would just have to write $this->db.

Original Answer

If by model you mean an Instance of Zend_Db_Table_Abstract then you want this in your application.ini file. Consult http://framework.zend.com/manual/en/zend.application.available-resources.html for an explanation on how to use the db resource and it's other options.

resources.db.adapter = "pdo_mysql"
resources.db.params.host = "localhost"
resources.db.params.username = "webuser"
resources.db.params.password = "XXXXXXX"
resources.db.params.dbname = "test"
resources.db.isDefaultTableAdapter = true
Ballsacian1
I do not want to use a table data gateway.
Billy ONeal
+1 for reduced code use suggestion.
Billy ONeal
+2  A: 

There's nothing wrong with sticking your default DB Adapter in a registry entry.

There's no built-in "default" database connection, since not every application uses a database.

One improvement (according to me) over your method:

Instead of setting things up in index.php, I typically initialize the adapter and stick in the registry in an initDb() method in Bootstrap.php (as created by the command-line project generation). That way it can be managed by Zend's the bootstrap mechanism.

timdev
+1  A: 

It's not a horrible hack. The Registry serves as a Service Locator in this case. This is the intention of the pattern. An alternative would be to use a Dependency Injection Container.

However, since you are likely just doing Zend_Registry::get('db') inside your model, you are creating a dependency on the Registry class, which makes your code somewhat hard to test. You cannot just mock the registry class in your UnitTests. It would be smarter to inject the registry instance from a model factory.

See this related question:

Gordon