UPDATE : the answer now reflects modern links and a better description.
Of course, there are many different ways to develop a plug-in system, and perhaps the task https://softwareengineering.stackexchange.com/ will give you more ideas, but I will try to help my ideas and experience.
I will talk about some of my own experiences that I learned from a series of my own frameworks. Agile UI and Agile Data currently support many of them for expansion, but I will focus on Components
HOOKS
When you try to enter code into an existing object, a hook is the standard way. This is the best option for expanding an application or structured stream.
During the refactoring of my frameworks, I split the capture implementation into a separate attribute and documented it here: http://agile-core.readthedocs.io/en/develop/hook.html
Host application:
... some code here .. $this->hook('beforeInit'); $this->init(); $this->hook('afterInit'); ... code goes on ..
Plugin:
$host_app->addHook('beforeInit', function($object) { echo "About to execute init of $object"; });
User interface components
Components are another design pattern that is suitable for user interfaces. You start with the page / app layout, which is then broken down into "Menu", "Title", "Footer", "Content".
A component is an object that can be associated with a layout or other component. Each component is capable of transmitting and transmitting additional HTML / JS to its parent element. Most components would also be interrupt objects.
This approach is called the "Render Tree", and the application runs through 2 stages - "initializing the rendering tree" and then "rendering".
Host Application:
$layout->menu = new \atk4\ui\Menu(); $layout->add($layout->menu, 'TopMenu');
The above code shows how a new component (menu) can be initialized and inserted into $layou
. In addition, the HTML output in $ menu is sent to the {$ TopMenu} tag, which is defined in the HTML layout template.
The plugin can interact with the render tree:
- adding more components anywhere in the tree
- Affects existing components (e.g. adds a new menu item)
- destruction of any existing component
When these approaches are combined, you can use something like this:
$app->addHook('afterInitLayout', function($app) { $app->layout->menu->destroy();
This can be used to replace the standard menu with a more powerful implementation from your add-on.
My component implementation is documented here:
http://agile-ui.readthedocs.io/en/latest/view.html#initializing-render-tree
SECTION UI / DATA
Although there may not be many answers to the question, yet another powerful way to expand is by sharing problems. All user interface components in Agile UI do not know how to do anything with data.
While many user interface generators require the developer to manually create and link them to the data, I entered the Model object as follows:
$form->setModel(new User($db));
Demo: http://ui.agiletoolkit.org/demos/form2.php (2nd form)
In this approach, the User
object contains enough metadata to fill in the Forms fields, the credits perform validation, and also save / load data.
Since the User class can also be declared in the add-in, it makes a pretty powerful way to extend existing functionality by adding support for new data objects.
OTHER APPROACHES
Some other extension approaches with add-ons include:
Factory:
Ability to resolve the class specified as a string in the namespace / file:
$api->add('MyClass');
Provides the ability to add standard classes for the reroute, but is not very friendly with the type hint in the IDE.
New Types / Features:
Add-on can provide new classes that add Persistences, Table columns, form fields, actions, etc.
Conclusion
I think adding deign comes down to:
- ease of installation and use
- Do I need an add-in to work in the finished form?
- avoid conflicts between add-ons
- definition of various types of add-ons - authentication, user interface, behavior
- may add extensions another addition
- Will complement application design, data and architecture?
- provide many opportunities for additions without sacrificing performance.