I have some custom logic I need to insert into CDbCommand, CDbTransaction & CActiveRecord classes that comes with the Yii framework. I can't replace them because I am using the same framework files for other projects.
Most of my models are already generated and is extended from CActiveRecord. I know I can easily switch them to my own custom class extended from CActiveRecord. However, the methods that I want to override in CDbCommand would not be filtered into CActiveRecord if I extend the CDbCommand class, and in addition CDbCommand is used by many other Framework classes. I need all other framework classes to use my overrides of CDbCommand methods.
Any ideas?
There has been a similar question in the yii forums, concerning classes like CHtml, which are caled statically all over the framework and in generated Code.
There seems to be no pretty way, the kind-of-consensus in the discussion was to do the following (example CHtml):
Move CHtml.php to Html.php and rename the class to Html.
Create a new, empty CHtml class, that extends Html.
Add your overwrites to the new CHtml class.
It's not pretty but it works and is reasonably maintanable on Yii updates.
Override
To override CDbCommand and CDbTransaction, you should override CDbConnection. Most of my Yii Projects have many Yii classes overridden including classes that are mentioned in your question. It is a lot of work, but you have few choices.
For me, it is good practice to begin projects with overriding all classes you use. Once you write your project template with custom ActiveRecord, DbConnection, DbCommand and DbTransaction, Html and widget classes, there will be no need to solve problem of extending Yii classes again.
Fork
Of course, you always can fork and add custom logic directly to Yii classes or adjust something to allow extend classes easily. Sometimes, it is the simplest solution.
== Correct Answer Added below ==
ORIGINAL ANSWER
As far as Yii 1.1.* is concerned the best way seems to be to place the overriding versions of the files into a folder such as
/protected/component/overridden/ folder
and then to bind the application to the custom classes by adding them to import configuration in
/protected/config/main.php.
'import'=>array(
'application.components.CDbConnection',
'application.components.CDbTransaction',
'application.components.CDbConnection',
...
),
This would then call the custom class files even when called by the Framework files.
CORRECT ANSWER - RESOLVED
What I needed was the following at the end of index.php (in the root of project)
Yii::$classMap= [
'CActiveRecord' => dirname(__FILE__) .
'/protected/components/auditAndOps/CActiveRecord.php',
'CDbCommand' => dirname(__FILE__) .
'/protected/components/auditAndOps/CDbCommand.php',
'CDbTransaction' => dirname(__FILE__) .
'/protected/components/auditAndOps/CDbTransaction.php',
];
Yii::createWebApplication($config)->run();
What this essentially does is to remap the original classMap locations of the respective Framework files, to my custom files in /protected/components/auditAndOps/
Related
I am currently creating a component for joomla, so I use PHP in POO with the MVC model of joomla! For my component I end up with a huge code of more than 3800 lines, I would like to factorize / separate this code so that it is more readable later.
To do this I would therefore like to separate the methods in a separate file in order to recall them in the code.
I tested several solution but which does not work, I mi a method in a file methode.php, I then used include ('methode.php'); but I have the impression that it does not work in an object.
I also tested the require and require_ once. as well as a joomla! : jimport ('method.php');
I think there is a relatively accessible solution to this problem, however I can not find a solution with my research.
Joomla loads classes, the method declarations need to be in the class that Joomla imports. I am not sure how the autoloader interferes with requires and imports. I would go about using inheritage. Build a base class that inherits from the appropriate joomla class and inherit a few times with incresing functionality. Not the intuitive way, but that's how I see Joomla do it.
I'm using CodeIgniter and I have a few utils that I want each controller (that is, each controller file) to have access to.
The question is: where to put these?
I thought of helpers, but the CI documentation talks only about extending existing helpers, not making your own. I'm sure that doesn't mean I can't make my own helpers, but it does mean I don't know how they should be built (procedural? Methods of the global CI instance? etc)
I also considered hooks, but this is a poor fit I think as I'm not extending core functionality.
Or is there some other way I'm missing?
It's been a while since I've done this but I believe I used two approaches.
Creating a new, custom helper that goes into /application/helpers, following steps noted from this answer: CodeIgniter: Create new helper?
Creating a new library class into /application/libraries which I also activate in the autoload configuration found in /applications/config/autoload.php. This way it's always available to my controllers when I need it. CI has good documentation on this one (http://ellislab.com/codeigniter/user-guide/general/creating_libraries.html).
I did it simply by adding a file to the application/helpers folder (maybe I created that folder - I can't remember) and then loading them in the usual way.
If you read the documentation for CakePHP on creating PlugIns. It clearly states that the PluginAppModel and PluginAppController base classes extend from the AppModel and AppController classes. Which are implemented in the application using the plugin.
This seems very risky to me.
A plugin doesn't have control over what callbacks, components, helpers, etc.. that an application may have configured in those base classes.
Is there any problems in having your PluginAppModel/PluginAppController extend just the base classes from the CakePHP lib. Like Model and Controller?
Can someone explain the logic in why a plugin should extend these application specific classes?
Not matter what you do, exclude the App* classes from the inheritage chain or if you include them. There will be always points of possible failure because it is not predictable what people do in these classes.
The less likely scenario is that things break in your plugin if you extend the App* base classes than when you would not extend them.
Auth and Session Component are in the case of a Controller a good reason why you should extend the App* classes. Behaviours in an AppModel another one.
If your plugin depends on a certain - unchanged - state of a property of the Controller or Model class you did something wrong while building that plugin in my opinion. It is better to keep your plugin flexible by providing configuration options or check the states of inherited properties and attached components and behaviours.
If there is really a pitfall in your plugin - I still think it's done wrong then - you should document it so that it can be integrated properly by people who read the documentation.
I asked this question previously : Codeigniter Class Inheritance between modules (wiredesigns)
I accepted an answer to that question which provided a way of doing what I want by extending a custom controller in application/core. This approach seemed sensible and offered the added benefit of allowing both modules to function independently.
However, Having thought about it, I am not sure this is the best approach for this situation because My Products controller will require almost all of the functionality of the item controller so this approach will leave my item controller almost empty - I'm not sure I like this.
QUESTION 1
Although I may still go with the approach previously suggested, I would like to know if there is a way to extend classes between modules so that I can weigh up the two options (see original question below)
QUESTION 2
Additionally, I think I should be able to re-use much of my model class, I can see that I would be able to do this using the MY_Model in app/core approach. But...
a) Is there a way to directly access another modules models?
b) Could I extend my models between modules in a similar way to question 1 for controllers
PREVIOUS QUESTION
My CI2 app is using the wiredesigns modular layout.
I have a two modules called item and product in a a folder called modules like so:
/application
/modules
/item
/product
In Item I have a controller called item which starts like this.
class Item extends MX_Controller
{
//code here
}
What do I need to do to make my products controller extend my item controller in a different module
The correct answer here is:
Don't
Why are you trying to do this? Place your logic into a library or some sort of shared file and implement a call to that library instead.
You could make Item an abstract class in your application/libraries folder and the autoloader built into HMVC will automatically load it. There is no reason this needs to be in a module, and it definitely doesn't need to be a controller.
I have a structure that is
application
application/modules
application/modules/default
application/modules/default/models
application/modules/admin
application/modules/admin/models
When calling controllers in admin I understand they must be named like Admin_TestController. This works fine, but my models in my admin module don't seem to be able to load. I have tried naming them and the files in all kinds of ways but it just doesn't seem to want to be able to load them. How should I name the file and model class in a module to be able to use it? I use autoloading.
What do your bootstrap files look like? That is the most import part of problem.
It is very important (in order for the namespaces to autoload) that you you have a bootstrap in each module (located # application/modules/admin/bootstrap.php) that should contain, at the very least:
class Reports_Bootstrap extends Zend_Application_Module_Bootstrap
Notice that it extends Zend_Application_Module_Bootstrap. This does the heavy lifting of registering the namespaces for the MVC of the module.
As Fatmuemoo states the bootstrap for the module should extend Zend_Application_Module_Bootstrap also you should include
resources.modules[] =
In your config. This is in the docs for Zend_Application_Resource_Modules
It seems you need to include a bootstrap class that extends Zend_Application_Module_Bootstrap for the modules you want to use. Check this forum post about a similar issue to see if it helps point you in the right way. Seems you may need more than one to load separate modules.