6

I have this module called 'olo' which handles all our online ordering stuff.

Now I have made a new module called 'olosec' because I wish make a different version with a slight changed flow, and some other changes in some of the controllers.

Is it possible for me to extend a controller in 'olosec' with a controller in 'olo'?

As of now I have tried

class Olosec_CartController extends Olo_CartController

Which throws an error like

Warning: include_once(Olo/CartController.php): failed to open stream: 
No such file or directory in /httpdocs/library/Zend/Loader.php on line 146 Warning:
include_once(): Failed opening 'Olo/CartController.php' for inclusion.
bla bla bla (include path) bla bla bla

My directory structure is something like this (thanks tree \F \A and EditPlus++)

+---application
|   +---views
|   |   +---scripts
|   |   +---layouts
|   |   |   +---default
|   |   |   +---admin
|   |   +---languages
|   |   +---helpers
|   +---modules
|   |   +---admin
|   |   +---mobile
|   |   +---olo
|   |   |   +---controllers
|   |       |       IndexController.php
|   |       |       MenuController.php
|   |       |       CartController.php
|   |       |       OrderlistController.php
|   |   |   |
|   |   |   +---models
|   |   |   \---views
|   |   |       +---helpers
|   |   |       \---scripts
|   |   |           +---index
|   |   |           +---menu
|   |   |           +---cart
|   |   |           \---orderlist
|   |   \---olosec
|   |       +---controllers
|   |       |       IndexController.php
|   |       |       MenuController.php
|   |       |       CartController.php
|   |       |       OrderlistController.php
|   |       |
|   |       +---models
|   |       \---views
|   |           +---helpers
|   |           \---scripts
|   |               +---index
|   |               +---menu
|   |               +---cart
|   |               \---orderlist
|   +---models
|   +---controllers
|   \---configs
+---library
+---public
|   +---cli
|   \---default
+---tests
\---data

Update

I have used this "nasty" hack which works

require_once( APPLICATION_PATH . '/modules/olo/controllers/CartController.php');

Update @ Rakesh

I have this in my bootstrap..

function _initAutoloader() {
    $autoloader = Zend_Loader_Autoloader::getInstance();
    $autoloader->setFallbackAutoloader(true);
    return $autoloader;
}

In my application.ini

autoloadernamespaces.0 = "Zend"
autoloadernamespaces.1 = "My"
autoloadernamespaces.2 = "Something"
Phliplip
  • 3,582
  • 2
  • 25
  • 42
  • @Tomalak Geret'kal: What's wrong with a friedly greeting ;) And yes, the 'i'.. I always forget to uppercase them. But thanks for the edit! – Phliplip May 05 '11 at 12:14
  • Though you meant only to be polite with your greeting, since Stack Overflow isn't a message board we prefer that questions just contain the question. It saves space, avoids bloat, and keeps the OCD happy. :) – Lightness Races in Orbit May 05 '11 at 12:17
  • @Tomalak Geret'kal: I'll keep that in mind ;) – Phliplip May 05 '11 at 12:19

2 Answers2

1

Why not have a custom library folder for common classes

application/
    library/    < for common classes

If you are using some classes not only in one controller but at many places in your project this is a good approach.

You just have to add this new application/library/ folder to your include path in your boostrap file.

Another approach is to have an action helper. But as I described the common classes folder should be a good solution. However I found some interesting resources, most of them are about cross module coding but they might help you anyway http://zend-framework-community.634137.n4.nabble.com/Code-re-use-across-modules-td668554.html and How to Use Same Models in Different Modules in Zend Framework?


Let me describe another approach

class BasicController extends Zend_Controller_Action
{
    public static $variable = '';

    public function init()
    {
        self::$variable = 'assign value';
    }
}

class HomeController extends BasicController
{
    public function indexAction()
    {
        $bioVar = parrent::$variable;
    }
}

This is better than simply extending controllers because they represent actions and each action has a corresponding view script. However all your classes should be registered in autoloader.

Community
  • 1
  • 1
DarkLeafyGreen
  • 69,338
  • 131
  • 383
  • 601
  • 1
    I allready have quite the extensive library, but the stuff that is in the controller class I wouldn't consider as something to put in the library - I understand your idea. But i see the library as a toolbox that I can reuse on another project, and controllers are classes that handles flow, input, model handling and preps data for the view-scripts. – Phliplip May 05 '11 at 10:48
1

If you have instantiate the class from Zend Autoloader, the error should go away.

You should have the following code in your bootstrap.php file:

protected function _initAutoloader()
{
    $autoloader = new Zend_Application_Module_Autoloader(array(
       'namespace' => '',
       'basePath'  => APPLICATION_PATH . '/modules',
    ));
    return $autoloader;
}

In general, the controllers are loaded via Zend_Controller_Dispatcher, you should use Zend_Application_Module_Autoloader to instantiate the class from other controllers.

Rakesh Sankar
  • 9,337
  • 4
  • 41
  • 66
  • 1
    Actually I decided that Extending the Order module to my Mobile module, could potentially be a very bad idea, as it's a different platform. So just went with a 'blank' module, and copied the bits i needed. But the idea of extending modules, could be a quite good idea for let's say an article/news module. – Phliplip May 27 '11 at 08:33
  • @Philiplip: Yes I agree. But for cases like mobile platform, you can re-use the code in the form of an API. You can make your module work as an API and normal flow with the help of view-action helper called "Context Switch" means you can switch the view to HTML, JSON or XML. That way, you don't have to copy your code to a different module for mobile, but have same code and switch the context based on the request. [http://framework.zend.com/manual/en/zend.controller.actionhelpers.html#zend.controller.actionhelpers.contextswitch] – Rakesh Sankar May 31 '11 at 05:02
  • So, let's say you want to access "comments" action in "xml" format from API, then you should do.. for ex: `if ($_SERVER["HTTP_HOST"] == "api.example.com") {$this->_helper->contextSwitch()->addActionContext('comments', array('xml', 'json'))->initContext();}` – Rakesh Sankar May 31 '11 at 05:07