Initiating objects in Zend Framework?

854 views Asked by At

How can I eliminate to write $object = new Application_Model_Database() in every controller?

For example for an article controller, I have to type $articles = new Application_Model_Articles() for every controller. Should I put it under viewer controller, action helpers, or any other way?

5

There are 5 answers

0
Jeremy Kendall On BEST ANSWER

Your question almost sounds like an OOP best practices question as opposed to a Zend Framework specific question. Regardless of whether or not I'm using a framework, and regardless of what framework I choose, I base when and where I create new objects on testability how many times I have to write $object = new My_Random_Object();.

Speaking specifically to the Zend Framework: Objects I'm going to use everywhere, or almost everywhere, get created in Bootstrap.php. These objects generally include a database adapter, logger, view object, and any plugins I might use. To access these across the application, I'll create private properties in the appropriate controllers and assign the objects to those properties in the controller's init() method.

class ExampleController extends Zend_Controller_Action
{

    public function init()
    {
        $bootstrap = $this->getInvokeArg('bootstrap');
        $this->_db = $bootstrap->getResource('db');
        $this->_log = $bootstrap->getResource('log');
        // and so on, and so forth
    }

}

Ideally, models, services, daos, etc, will all be relatively tightly grouped by controller and by action. In my experience, and this is speaking generally, if I have the same model or service class showing up across all of the controllers in my application, I have an organization problem. That being said, any model that shows up in only one action gets created in that action. If it's across actions in a controller, it gets created in the init() method and assigned to a property. If it shows up across multiple controllers, it gets created in my Bootstrap.php.

(Ideally, everything gets created in the Bootstrap.php, so you can swap out that bootstrap for testing purposes. Sadly, I don't always do that, and I most often use the principles I outlined above.)

1
Iznogood On

Well do you really need it in every controllers? Because that's pretty much by design. You implement models when you need them. Its not that much code really.

Now if its to be used across actions from a controller you could always:

class MyController extends Zend_Controllers{
     $protected $_articleModel;

...

and in your constructor or __init() function initialize it so you can use it in every action thru $this->_articleModel

If you REALLY want it everywhere in your application just initialize it in your bootstrap and store it in the registry.

public function __initModels(){
  $articles = new Application_Model_Articles() 
  Zend_Registry::set('articles', $articles );
}

And access it in your controllers like so:

Zend_Registry::get('articles')->fetchAll();

But then your still writing a couple of characters.

Hope this help!

0
dinopmi On

Another possibility is to use a Dependency Injection container, such as the Symfony DI component. It takes care of instantiating your objects, and you get some additional benefits:

  • Separation of concerns. You have a component devoted to create your object tree.
  • Easier testability of the objects.
  • Last, but not least, the performance benefits given by lazy instantiation (objects are created only when you ask for them). Thus, if some object is not used by the particular controller serving your request, it's not instantiated).

It's a bit more laborious than the above solutions, but much more flexible if you need to maintain and extend your application in the future.

Hope that helps,

2
coolguy On

IF you want to use models in the controllers you must call it..anyway some shortcuts are here

1.You can initialize it in the init section of your controller like

public function init(){
   $this->object = new Application_Model_Database();
}

So that the this->object is available in all the actions of that particular controller

2.Use Zend_registry as suggested in the above answer

1
RockyFord On

If you are using this object to just display data in your view and are using your controller to grab the data and assign it to your view, like so:

//someControllerAction
$object = new Application_Model_Articles();
$object->fetchAll();
//assign to view
$this->view->articles = $object;

You might be better off making a view helper similar to:

//Articles.php put in /application/views/helpers  
class Zend_View_Helper_Articles extends Zend_View_Helper_Abstract {

public function Articles() {

$articles = new Application_Model_Articles();
$articles->fetchAll();
//return rowset object
return $articles;

Then in your view (phtml) you could do something like:

//someView.phmtl
<?php $articles = $this->Articles(); ?>
<h1><?php echo $this->escape($articles->title); ?></h1>
<p><?php echo $this->escape($articles->body); ?></p>

building a view helper allows you to bypass the controller completely if you just need to display data from the model. This is a very simple example and can be used with partials and partialLoops.
REF:ZF reference Custom View Helper
ZF partial view helper reference