4

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.

Matt McCormick
  • 13,041
  • 22
  • 75
  • 83
  • Is your autoloader loaded with the correct include paths? Some Zend installations don't use the autoloader (the controller you're requesting in the URL is explicitly loaded during dispatch). The reason it works in library is because that's in your include path. Do any of the other controllers work as an extend? Can we see the Api_ApiController decl? – Matt S May 27 '10 at 16:21
  • No, the other controllers do not work as children. I am trying to set that up. The autoloader is not setup in any specific way during the application launch. Perhaps that is the reason. I am not so familiar with the autoloader so I will look into that. Have edited the question with Api_ApiController. – Matt McCormick May 27 '10 at 16:27

2 Answers2

7

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
  • 82,642
  • 24
  • 155
  • 189
  • 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 May 28 '10 at 15:25
0

[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
  • 14,144
  • 4
  • 42
  • 64
  • 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 May 27 '10 at 16:40