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.
Related
I'm extending the functionality of an existing Symfony-based application and have found that additional bundles and using bundle inheritance has worked well to customise the functionality.
I've now found myself wanting to inherit from an existing bundle to customise its functionality but I also need to add some additional entities and extend the existing ones. The documentation suggests it might not be possible to extend an existing one since the entity is not a mapped superclass.
Is there anything I can do in this case? I basically want to retain the vast majority of the functionality of the existing bundle, but be able to collect more data.
EDIT:
I've looked into Doctrine inheritance and everything seems to require I have access to the top-level class in order to extend it. Which isn't ideal, as I'd like to keep that class the same.
Imagine I've got a class defining an entity, such as a Product.
My framework is structured in toggable modules, such that some modules may extend the default class, i.e:
Module1 lets me define a ColoredProduct
Module2 lets me define a ShapedProduct
How would I define the relations between ColoredProduct, ShapedProduct and Product? How can I make sure that I can get a dynamic relation (toggle one or another without code intervention)?
Do I extend the class product? Do I refer to it on each subclass?
I'm using PHP. Thanks for your input.
This sounds like you are looking for a class hierarchy:
Product is the superclass
ColoredProduct and ShapedProduct are subclasses.
You need no additional code since the subclasses inherit methods and properties from the Product superclass.
Depending on how you implement modules this could also be solved using Interfaces or traits.
If your question is more about designing application modules that are related this may be of interest: what is the difference between loose coupling and tight coupling in object oriented paradigm?.
For a very good example of how independend modules can be designed in PHP you have to look at the Modules in Yii2 Framework.
I'm trying to get to grips with the power behind Joomla (3.x)'s framework.
I've noticed that there are multiple types of model that can be used in a component:
JModelAdmin
Prototype admin model. Acts as a Factory class for application specific objects and provides many supporting API functions.
JModelLegacy
Base class for a Joomla Model
Acts as a Factory class for application specific objects and provides many supporting API functions.
JModelList
Model class for handling lists of items.
Acts as a Factory class for application specific objects and provides many supporting API functions.
JModelForm
Prototype form model.
Acts as a Factory class for application specific objects and provides many supporting API functions.
JModelItem
Prototype item model.
I understand that JModelLegacy seems to be the foundation class. My models have been extending JModelLegacy by default, however, I was wondering if I could be potentially using the benefits from the other classes.
If there was someone who knows about these models, I would appreciate having an explanation about what the differences are between these model classes, and an intended scenario where you would use one over others.
First of all all the classes are available for code study under:
\libraries\legacy\model\
It's also important to understand that these classes should be used (generally speaking) in connection with the corresponding controllers: JControllerLegacy, JControllerForm and JControllerAdmin.
JModelLegacy - is the base class for the Joomla model (model as in MVC). It will basically work as a Factory class by initializing the database driver object and the table object.
You may want to extend this class if you just want to do some basic SQL queries (any work with JDatabase) and write other business logic.
All models will extend JModelLegacy.
JModelList - is a class for handling lists of items. It provides pagination and filtering. Basically everywhere you display a list of items, you can use JModelList. All core components rely on JModelList.
JModelForm and JModelAdmin are generally associated with forms. Forms can be the the User registration form or creating and editing a record. Forms in Joomla are defined in XML files. JModelForm will load this files as JForm objects, will load form data, preprocess the form and validate it.
This is one of the most powerful classes that you can use. They will do the heavy lifting. When you don't like a specific behaviour you can override it by implementing your own code.
JModelAdmin adds some extra admin functionalities to the form:
perform batch operations on records.
will do ACL checks on records.
JModelAdmin will generally be used when editing a record or for batch operations, especially in backend.
JModelItem - very unlikely you will need it. It exposes just a method getStoreId() and two properties. You won't need this class, unless for as a naming thing, instead of using JModelLegacy you want to extend it when doing something basic, such as displaying a record. (my personal understanding of things).
Conclusion: Above is a general introduction to this classes, as I see them. My suggestion is to look into detail how Joomla uses them, what methods are exposed and how to use them. They are very powerful classes, and especially for CRUD operations they will help you do all the heavy lifting. After you understand what they do, you can use them and override them when needed.
I have read a lot of SO topics about this already, but still haven't found (or have been able to create) a proper answer.
I am working on a small MVC framework and I want some global class/object that I can call from my controllers (but maybe models too).
There are a couple of routes I can take:
Global variable
Static class/Registry
Dependency injection
The internet seems to agree that the DI is the best route to take. I think I have grasped the idea, but am not comfortable yet. So I want to throw in some background information; I will probably be the only one working on the project, it is a small project, all my controllers extend the main Controller (so I could just load one library like class there).
As a concrete example, I want to have an array of categories. So I started out with putting that array in the CategoryController. But now I noticed I kinda want to use that array in my frontview and in ProductController as well. Obviously I don't want to load all of CategoryController into ProductController.
You could also say I could put that array in some kind of configuration or settings file, because of the simpleness of this example, but that's why it's an example. I will probably expand on it with more functionality.
So to summarize: In PHP (specifically inside a MVC model) how can you give your classes (mainly Controllers) access to some kind of common class or other sharable functionality.
Your controllers are created by "something" (usually a front controller). So when the controller is created, you could inject a dependency injection container.
And in your configuration/bootstrap (before the controller is created), you should add you categories to the container.
That way you can access the categories from every controller.
Please note that this is a simple example that doesn't totally fit the spirit of dependency injection. The best solution would be to inject directly the categories (instead of injecting the container). But that can become a lot of work if you generalize that pattern (lots of dependencies to handle in your front controller).
A solution would be to use a dependency injection framework that could do that for you.
For example I work on a DI container that lets you inject stuff with annotations (PHP-DI), but there are several other libraries for DI so you have a choice.
My 2 cents:
In a small self-made mini-framework I have done some time ago, I have created a global singleton class named Application, and anything/everything which should be accessible from anywhere/everywhere was a property or method of this class.
In my case, there was a $db property for database access, a $user property to access the user data and methods, an $input property for a "powered" $_REQUEST access, and so on.
Of course, you have many other options, suitable for different scenarios. This approach simply worked fine for me on that occasion.
Now, if you want to access a controller from another controller, this really sounds strange. This "thing" that you want to access should be a model class, a library class, or anything else, but it should not be "locked" inside a controller class. Indeed, the controller should be "as thin as possible", and focus on calling the appropriated methods from other classes, based on the user input (request) and then calling some output method to generate and send the answer (response).
Finally, although I've read some criticism and complaints about it (as well as praises too), I do make use of static methods a lot, mainly for classes which are more "helpers" than anything else.
Is there any way to create a function that works for all controllers in Codeigniter at init?
In Zend there is a application/Bootstrap.php, i need some solution like that.
You could extend the native CI_Controller class and create a MY_Controller class that all of your application's controllers would extend. Methods in the MY_Controller class would then be available to every controller that extends it. You could also put code in the MY_Controller constructor that would be executed each time a child controller was constructed.
I don't remember exactly how the Bootstrap file works in Zend, but if this sounds like a viable solution the Creating Core System Classes section of the documentation explains how to extend the native controller.
You can extend your New_controller to CI_Controller. In New_controller you can write common function which you want. For use about new extended controller you can see this link:
The subject of extending core controllers is discussed briefly in a few places in the manual - specifically in the Core Classes and Creating Libraries pages.
The intent of extending the core Controller is to provide methods and attributes to all your normal Controllers. There are other ways of providing this kind of pervasive functionality - including Hooks, Libraries and Helpers. You should familiarise yourself with the methods and benefits of those alternatives before assuming the following is the answer to your question.
Finally, it’s assumed that you have an application that does something - it doesn’t matter what, merely that you have an existing Controller that we can work with here.
-extend_the_CI_Controller