Extending models/components from Module

I have created a module for backend admin management of our website. This module includes a separate backend login for the website. I want to avoid rewriting code already built for the application, so want to extend certain models/components inside the module in order to re-use previously written code.

So, for example, I want to extend the UserIdentity object inside my module with application.components.UserIdentity. I have tried using the following code to extend the Module’s UserIdentity component:


Yii::import('application.components.UserIdentity'); 


class UserIdentity extends UserIdentity

However this results in the following error:

Fatal error: Class ‘UserIdentity’ not found in /Applications/MAMP/htdocs/protected/modules/backend/components/UserIdentity.php

I have also tried adding the following line (setImport ‘application.components.UserIdentity’) inside WebModule as follows:


public function init()

{

	// this method is called when the module is being created

	// you may place code here to customize the module or the application

	

	// import the module-level models and components

	$this->setImport(array(

		'backend.models.*',

		'backend.components.*',

               'application.components.UserIdentity',

	));



But this results in the module simply using the UserIdentity class located inside the application’s component folder instead of the UserIdentity stored in the module’s component folder.

Any idea what I can do to get the UserIdentity class in the module to extend from the UserIdentity class in the application?

Cheers!

You should choose a new name for the child class, just as you did with UserIdentity. You cannot have two classes with the same name at one time (unless you start using namespaces, which I’m not sure how well they would fit in with Yii).

Yes, you are right, he should choose another name, but there is a problem with setImport().

Look, I have a module ‘MyModule’ and I want to inherit my controllers from Controller component inside components folder in my module (/protected/modules/mymodule/components/Controller.php), for example:


class CatalogueItemController extends Controller

As you know in the application folder /protected/components we also have such component (Controller). So this should raise an error - we have to classes with the same name "Controller". But nothing is happend. Application works and my module controllers just extend Controller component from /protected/components folder.

Inside MyModuleModule.php is:


public function init()	{

     // import the module-level models and components

     $this->setImport(array(

         'mymodule.models.*',

	 'mymodule.components.*',

     ));

}

It seems like setImport() doesn’t work… ?

It works, but only if the module gets loaded. Remember, most classes are lazy loaded. And that includes modules!

So unless you access the module directly (http://path/to/site/MyModule), you’ll need to instantiate it manually.


Yii::app()->getModule("MyModule");

Then the init() function will run and call the setImport().

However, this will only work for models, components, extensions, etc. It will NOT work for controllers because the controller gets loaded first.

So, there are two ways to do this.

  1. Hack

Yii::import("application.modules.MyModule.components.Controller");

class CatalogueItemController extends Controller

{

}



  1. Set the loading in protected/config/main.php

// autoloading model and component classes

	'import'=>array(

		'application.models.*',

		'application.components.*',

		'application.modules.MyModule.models.*',

		'application.modules.MyModule.components.*',

	),

The latter is better. It’s not hackish, and you don’t need to put it into every file you’re extending.

But I access my module exactly in direct way! path/to/site/MyModule/catalogueItem/update … !!!

And I don’t understand what is going on ((

Ah. You should’ve started a new thread instead of replying to an old one. Your problem is different than the OPs.

He wanted his main application class to extend from the module class, but you want your module class to extend from another module class (same module).

Again, the setImport() is working properly. The problem is the the import order. In the protected/config/main.php, you have


'import'=>array(

    'application.models.*',

    'application.components.*',

),

Then in the module, you have:


public function init()  {

     // import the module-level models and components

     $this->setImport(array(

         'mymodule.models.*',

         'mymodule.components.*',

     ));

}

So when you call the class in the module:


class CatalogueItemController extends Controller

It’s working exactly as intended. There is currently no “Controller” class set, so it goes through the import folders in order to find and lazy-load it. It finds the first one, which is in application.components.Controller, so it uses that.

That said, the solution is simple. In fact, it’s the same exact answer as given to the original and different question:

STOP putting two classes with the same name in your application! Rename one of them.

Ahaaa! The main thing is lazy-loading! Its behaviour. So as I understood, when system had found class Controller it stopped further import… And as result - there is no exception ))

But I thought that lazy-loading is used only in this way:


Yii->app()->getModule('mymodule')

and not in direct module accessing.

You see it’s not about naming the classes, it’s about understanding Yii workflow )