views:

293

answers:

2

I have the following directory structure:

modules/
  api/
    controllers/
      ApiController.php
      InventoryController.php
      OtherController.php

The init() method is common amongst multiple Controllers so I want to refactor that into a parent Controller class such as:

class Api_ApiController extends Zend_Controller_Action
{
    public function init()
    {
        // common code
    }
}

When I try:

class Api_InventoryController extends Api_ApiController

I get:

Fatal error: Class 'Api_ApiController' not found in /application/modules/api/controllers/InventoryController.php on line 4

Why does Zend Framework not map Api_ApiController to modules/api/controllers/ApiController.php?

I have figure out a way around this by putting the ApiController in the library/ and registering the namespace but it seems like a hack to me.

A: 

[Heavily edited. Please ignore my previous answer; I misread the question. Carelessness on my part.]

Did you instantiate the autoloader in your Bootstrap? Something like:

protected function _initAutoloader()
{
    $autoloader = new Zend_Application_Module_Autoloader(array(
        'namespace' => '',
        'basePath'  => APPLICATION_PATH . '/modules',
    ));
    return $autoloader;
}
David Weinraub
Am I correct that the 'BaseController' in your example needs to go in the library/ directory? There is no way to put it in the modules/api/controllers/ directory?
Matt McCormick
+3  A: 

The "problem" is, that ZF does not register the controllers directory in the autoloader as the controllers normally are loaded via the Zend_Controller_Dispatcher. The Zend_Application_Module_Autoloader, that's instantiated in the bootstrapper on the other hand only registers

        'dbtable' => array(
            'namespace' => 'Model_DbTable',
            'path'      => 'models/DbTable',
        ),
        'mappers' => array(
            'namespace' => 'Model_Mapper',
            'path'      => 'models/mappers',
        ),
        'form'    => array(
            'namespace' => 'Form',
            'path'      => 'forms',
        ),
        'model'   => array(
            'namespace' => 'Model',
            'path'      => 'models',
        ),
        'plugin'  => array(
            'namespace' => 'Plugin',
            'path'      => 'plugins',
        ),
        'service' => array(
            'namespace' => 'Service',
            'path'      => 'services',
        ),
        'viewhelper' => array(
            'namespace' => 'View_Helper',
            'path'      => 'views/helpers',
        ),
        'viewfilter' => array(
            'namespace' => 'View_Filter',
            'path'      => 'views/filters',
        )

So either you include your base controller script with require_once or you modifiy your autoloader to also include the controller directories.

Stefan Gehrig
I marked this as the accepted answer as it helped me understand how ZF works in this regard, especially the difference between the Dispatcher and the Autoloader. I ended up just using my original solution of placing a class Controller_ApiController under library/Controller/ApiController.php and adding the Controller_ namespace to the Autoloder.
Matt McCormick