Plugin Architecture in PHP - php

I am planning on doing a research on how to implement a plug-in architecture in PHP. I have tried searching the web for possible references, but I thought that maybe my search for a good reference would be faster and more relevant if I asked here.
Has anyone here tried using plug-in architecture for web projects?
Thanks,
Erwin

I have written wordpress plugins and the magic that they rely on is "Variable Function Names". For instance this is valid php, in which the function call phpinfo() will be called:
$func_name="phpinfo";
$func_name();
This allows developer to "Hook" function calls, as in override them with their own functions without having change the rest of the application. Linux Kernel modules are all about "hooking", they wouldn't work without this behavior.
Unfortunately for PHP variable function names are a disgusting hack that consumes a lot of resources. All functions in a name space are put in a list and this list has to be searched though before the function is called, this is O(log2(n)). Also keep in mind that Variable Function Names can not be accelerated properly in HipHop although the code will still be transformed into valid C++. A better approach would be to re-declare functions like you can in python which would be O(1) complexity, but the PHP development team HATES this idea (Yes, I've asked for this feature!).
Good luck!

There are a lot of concepts that can be considered a 'plugin'. You can write a plugin system using:
Event dispatchers (see the Symfony Event Dispatcher)
Middlewares (see Silex middlewares)
Observer OO pattern (see Google / Wikipedia)
And many others

You could take a look at how Zend Framework implemented their Plugin Loader component.
Basically you set path´s to where plugins are stored and the loader tries to load the first plugin found in a LIFO way.

What about these two classes
Plugin Handler/Loader
Plugin
and there are some rules
Plugin Handler/Loader is a singleton class and manages all child clases of Plugin Class.
Any plugins should have to be inherited from Plugin Class.
Plugin Class would have pre-defined properties and methods which can be overwritten by its child classes, so alternate method to hook system (but i am not sure of any major difference in results).
For example say Plugin class has a property of url_routes with default value of an empty array, the child class can then overwrite and add any required urls in this array.
Plugin Handler/Loader will then add these url routes from child class to underlying system.

don't forget about function __autoload. you can dynamically load components.
like:
SomeModule::test();
function __autoload($class)
{
$class = preg_replace('/^\W/', '', strtolower($class));
include 'modules/'.$class.'.php';
}

Related

factorize a php object separate the methods for a joomla component

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.

Grouping/encapsulating related functions that are across multiple php files

I'm working on an app, and part of functionality of this app is that it is extendable through addons.
The main app uses has a Render class that contains a lot of static methods that have to do with output. The actual methods interact with models/views, but the basic idea is that the Render class encapsulates methods that render something, like:
// To output "hello"
Render::sayHello();
// To output a picture of a cat wearing a hat
Render::catWithHat();
Now, from time to time addons require their own unique output functions. These output functions are very similar to the Render methods. So...
My first thought was that it would be great if I could dynamically add methods to the Render class, but after reading up about on-the-fly method creation it sounds like that's generally not considered very good practice.
So then I thought, well, I could just not encapsulate the addons' render functions at all. So that you'd just call them like:
renderMyAddonOutput();
I don't love that idea either, though.
So I guess I'm just wondering what would be considered best practice for encapsulating related functions that are declared across a variety of files.
Thoughts?
Note: if it makes any difference, I'm using Laravel for this (the very latest version).
I would consider using a Plugin pattern where an add-on registers itself into some kind of static container on init, and then you can use PHP's magic method __call() or __callStatic() to check the plugin array when a method is called that isn't found in the base class..
So if you had:
Render::pluginMethod()
then __callStatic() would check your plugin registry (which can be as simple as a static array of plugin classes or methods) and if it finds that method, it calls/returns it.

PHP: How to control multiple instances of Class in MVC (where multiple modules load) without Singleton

I am creating a very basic application framework for my project that uses the standard MVC approach and has support for modules (which I'm calling apps). There are a number of global objects created like $URI, $ROUTER, $PROFILE, etc. and access to global libraries like Array Helpers and Calendar generators. All of it is similar to Codeigniter or FuelPHP and any number of other frameworks, but we wanted something specific to our needs and decided to go from scratch (borrowing and modifying some libraries from the above).
My question is this. If one module loads the Calendar library, and the Calendar Library has no need for constructor variables or dependencies (i.e. every new \Calendar) will be identical), is there a way to ensure that only one calendar object is created? So if Module 2 tries to create a Calender Object that Module 1 has already created, the system would deliver the same object. I should clarify that multiple modules can run at once (why we needed a new framework).
I've heard terrible things about singletons and haven't been impressed with factories (which I may not be using correctly).
What is best practice?
Thanks!
How about an inversion of control system? You could make a global IOC object that has instructions for creating an object, but that also has a registry that contains references to already created objects. In the registration portion of the module for each item that you want to behave "singletonny", you simply check to see if it's already been instantiated.
The only other option I can think of is that since you aren't looking to construct anything, make it a static class that you can't instantiate and access the class statically (Calendar::printSomeFunction).
I am not, however, opposed to the singleton pattern, for what it's worth, when it's used correctly. I just choose more elegant solutions such as #1 here, because it is very flexible. You don't however have much control over whether or not a dev creates a class outside of the IOC module so you might consider protecting that in some way.
Hope that helps your decision making process.
What if you used a session flag?
if(!$_SESSION['calender']){
$calander = new Calander();
$_SESSION['calender'] = true;
}
Would this work for you?
What you'll want is something like a service container. Like:
$server_container->add_service("my calendar", "Calendar");
Then any module that needs a calender (or "my calendar" in specific) can be constructed with:
$mymodule = new MyModule($service_container->get_service("my calendar"));
class MyModule {
public function __construct(Calendar $calendar) { /*..*/ }
}
Singletons are bad because it makes your code untestable. With code like the above you can replace $calendar by a stub that implements Calendar. Proper DI would argue that you need a CalendarInterface too but you might have dependencies that don't allow you to make that distinction.

A php plugin architecture

I'm trying to think of a way to create a plugin architecture for my own framework. I've read numerous topics and post here and on other sites. And basically i've came to the following solution which seems to be the only good option in PHP (currently).
The idea is that every class extends a sort of observer like class. So a Template class, BaseController etc. always extend a 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 happends here is that when an indexController extends a baseController a plugin check is done. In this case for the constructor. This can be convenient when you want to do a some sort of login check with a plugin, before an Action method is actually invoked.
The Plugin class can resolve from what class is got called from and knows for what functions to look for in the loaded plugins.
Also note that it checks the loaded plugin list 2 times. One before anything is loaded (early) in the constructor, and one when all vars are loaded (late).
I can also add variables to the "checkForLateHooks()" function. So the hook functions can manipulate those too, like the 'baseLayout' variable.
A hook function would look like this:
public function hookConstruct ( &$baseLayout )
{
$baseLayout = 'login.html';
}
Now basically my question is, is this approach any good? I know there are probably alot of other ways to do it too. But i mainly don't want to run into design problems later on. It seems like a good idea now, but you never know how things work out later on...
If i remember it right (from all the posts the i've read), this is kinda like WordPress does it (and some other frameworks).
UPDATE: answer now reflects the up-to-date links and better description.
There are certainly many different ways to design a plugin system and perhaps asking on https://softwareengineering.stackexchange.com/ would give you more ideas, but I'll try to help by sharing my ideas and experience.
I'll share some of my own experiences which I've learned through a series of my own frameworks. Currently Agile UI and Agile Data both support many wasy to be extended, but I'll focus on the "Components"
HOOKS
When you look to inject code into the existing object, a hook is a standard way to go. It's the best option for extending the application or flow with an established structure.
While refactoring my frameworks, I've separated hook implementation into a separate trait 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";
});
UI COMPONENTS
Components present a different design pattern, which is suitable for the User Interfaces. You start with the page/app layout which is then broken down into Menu, Header, Footer, Content.
A component is an object which can be associated with Layout or the other component. Each component is capable of rendering and passing extra HTML/JS to its parent. Most of components would also be an interractive objects.
This approach is called "Render Tree" and application execution goes through 2 stages - "initialization of a render tree" and then "rendering".
Host Application:
$layout->menu = new \atk4\ui\Menu();
$layout->add($layout->menu, 'TopMenu');
The above code show how a new Component (Menu) can be initialized and inserted into the $layou. Furthermore the HTML output of $menu is directed into {$TopMenu} tag, which is defined in the HTML template of Layout.
Plug-in can interact with the render tree by:
adding more components anywhere in the tree
affecting existing components (e.g. add new menu item)
destroying any of the existing components
When those 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 standard menu with a more powerful implementation from your add-on.
My implementation of components is documented here:
http://agile-ui.readthedocs.io/en/latest/view.html#initializing-render-tree
UI / DATA SEPARATION
Although perhaps not so much answer for a question, but another powerful way to extending is a separation of concerns. All of the UI components in Agile UI do not know how to do anything with data.
While many UI generators require developer to manually build them up and link up with data, I am injecting "Model" object like this:
$form->setModel(new User($db)); // populates name, surname and gender fields
Demo: http://ui.agiletoolkit.org/demos/form2.php (2nd form)
In this approach object User contains enough meta-data for the Form to populate it's fields, captions perform validation and also save/load data.
Since "User" class can also be declared in an add-on it makes a pretty powerful way to extend existing functionality by adding support for new data entities.
OTHER APPROACHES
Some other approaches to extend with add-ons include:
Factory:
The ability to resolve class specified as a string into namespace / file:
$api->add('MyClass');
Gives ability for add-on to re-route standard classes but is not very friendly with type-hinting in IDEs.
New types / Traits:
Add-on can provide new classes adding Persistences, Table Columns, Form Fields, Actions etc.
CONCLUSION
I think add-on deign boils down to:
simplicity of installation and use
does add-on need to operate out-of-the-box?
avoiding conflicts between add-ons
defining different add-on types - authentication, UI, behaviour
can add-on extend another add-on
will add-on fit application design, data and architecture?
give a lot of power to add-ons without sacrificing performance
Have a look at PHPPlugin on https://github.com/gheevel/PHPPlugin. A simple PHP plugin framework inspired by eclipse and jira plugin architectures. Basically, your application can define extension points and plugin instances can register on those extension points for providing extra functionality. Works well in combination with composer and/or symfony.

How to customize Zend_Tool output?

I'd like to use Zend_Tool (ZF 1.9) with my project, but I would like to be able to customize the default output of new files. For example, all Controllers should have a specific header pre-pended to the output with phpdoc markup and licensing information to avoid me having to add this as an extra step.
Also, for this particular project (but not all other projects), I need the controllers to extend something other than the default Zend controller as I have extended that for some specific functionality.
The documentation alludes to the ability to do these things, but it does not make it very clear.
From what I can tell I can set up a ~/.zf directory (on ***nix based systems) and include custom providers there. However, this will be machine-wide as opposed to limited to single project scope. Also, while this will add new providers it does not (seemingly) allow me to customize the functionality of existing providers.
Any help here would be greatly appreciated!
Essentially what Jacob was getting at: what you're talking seems like simple class extending. There's a really simple slideshow introduction to extending Zend Framework here:
http://www.slideshare.net/PHPBelgium/extending-zend-framework-presentation
There are also lots of other resources available online for extending Zend Framework. You can create separate source trees for your different projects, and functionality common to various projects can be added to abstract classes that are in common folders. Something like this isn't common, but I've found it works in those kinds of situations:
class My_Component_HelloProvider extends My_Common_Component_HelloProvider
{
public function say()
{
echo 'Hello from my provider!';
}
// public function do() is inherited
}
class My_Common_Component_HelloProvider
implements Zend_Tool_Framework_Provider_Interface
{
public function do()
{
// do something
}
}
Let me know if this is different from what you're trying to do, but there's no reason you can't build multiple applcation extensions from a single instance of ZF.
You can naturally continue to override when you define the specific classes. You can declare them to be based on your class, rather than the ZF class.
For specific projects, you can modify your classpath to be a custom version of ZF or possibly have a custom override folder. With a custom folder then your changes are not machine wide, but neither is your zend framework. on ***nix based systems, you can leverage symbolic links to keep yourself to one copy of ZF.
Are you trying to modify your source code to include the license headers and PHPdoc? If so, what I have done in the past is have a simple build step that adds the information you need. Each file type can have the appropriate header information. You can have nice tags to tell the system to ignore files, or only run on controllers.
Good Luck,
Jacob

Categories