Php plugin architecture

I am trying to come up with a way to create a plugin architecture for my own structure. I read a lot of topics and posted here and on other sites. And basically, I came up with the following solution, which seems to be the only good option in PHP (currently).

The idea is that each class extends a kind of observer, like a class. Thus, the class Template, BaseController, etc. Always extend the Plugin class.

class BaseController extends Plugin { public function __construct() { // Plugin check, notify all loaded plugins $this->checkForEarlyHooks(); // Init some standard stuff $this->view = new Template(); $this->baseLayout = 'layout.html'; $this->something = new Something(); // Plugin check, notify all loaded plugins $this->checkForLateHooks(); } } 

So what basically happens here is that when indexController extends baseController, a plugin check is done. In this case, for the constructor. This can be convenient if you want to perform some kind of login check with the plugin before the Action method is actually called.

The Plugin class can decide which class is called and knows which functions to look for in loadable plugins.

Also note that it checks the downloaded list of plugins 2 times. Before something loads (earlier) in the constructor and when all the vars are loaded (later).

I can also add variables to the checkForLateHooks () function. Thus, hook functions can also manipulate them, for example, the baseLayout variable.

The hook function will look like this:

 public function hookConstruct ( &$baseLayout ) { $baseLayout = 'login.html'; } 

Now basically my question is: is this approach some good? I know that there may be many other ways to do this. But I basically don't want to run into design issues later. It seems like a good idea now, but you never know how things will develop later ...

If I remember correctly (from all the posts I read), this is similar to WordPress (and some other frameworks).

+6
source share
2 answers

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(); // remove default menu $app->layout->menu = new \plugin\SuperMenu(); $app->layout->add($app->layout->menu); }); 

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)); // populates name, surname and gender fields 

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.
+5
source

Take a look at PHPPlugin at https://github.com/gheevel/PHPPlugin . Simple PHP plugin infrastructure inspired by the eclipse and jira plugin architecture. Basically, your application can define extension points, and plugin instances can register with these extension points to provide additional functionality. Works well in combination with composer and / or symfony.

+1
source

Source: https://habr.com/ru/post/912646/


All Articles