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 b开发者_高级运维asic here?
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
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.
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
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:
- Zend_Registry: real life examples
精彩评论