Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Class Autoloading?
#1
I'd been thinking to write a tutorial recently (which would go on the wiki) on how to build a relatively simple GS blog plugin from scratch. This would utilise OOP techniques to accomplish it elegantly. Currently, GetSimple statically uses the include/require functions in the plugin files, but this leads to problems when there are multiple plugin dependencies (i.e. if the plugins are loaded in the wrong order, the classes will not exist yet in the runtime).

To remedy this, is it possible that a plugin hook be created for autoloading classes? It would be a hook that takes a function (or object method) name and add it to the autoload stack. This ensures that regardless of the order in which the plugins are loaded, when a class is needed, it will be loaded if it hasn't yet.

All the hook needs to do (in the pre-header or pre-template) is queue all of the functions called to by that hook, then loop through the queue, using spl_autoload_register to add that function to the autoload stack.

Example:
PHP Code:
// Code for plugin developers (in their plugin_name.php file
// 1. In your plugin, use the autoload hook
add_hook'autoload''my_autoloader' ); // adds function 'my_autoloader' to queue/array called $autoloaders

// 2. define your autoloader (for example, this one assumes a file structure '/plugins/plugin_name/Classname.class.php')
function my_autoloader($class) {
  
$file 'plugin_name/'$file 'class.php'
  
if (file_exists($file)) include($file);


PHP Code:
// algorithm for how the hook works (to be integrated into core)
foreach ($autoloaders as $function) {
  
spl_autoload_register($function)

Reply
#2
plugins should not do stuff in runtime, they should wait until common hook and then init.
seems like the easiest solution.
NEW: SA Admin Toolbar Plugin | View All My Plugins
- Shawn A aka Tablatronix
Reply
#3
In waiting for the common hook, isn't it still necessary to hard-code the includes in the required hierarchical order? I can see why it would be the easiest solution if (when the common hook is called) all of the class files (including the ones in any other dependent plugins) are loaded. Can you give a simple example of how this would be ensured?
Reply
#4
Yeah the classes will be available when they are included, problem would then be extending classes, which would have to be deferred.

The common hook is called after all plugins are loaded ( included ), which in turn include all their classes. So they should all be available at that point.

Now if you are talking about dynamically instantiating classes, then that will indeed be a problem, but php has actual autoloading built in to 5.3, so you can probably do something with that on your own. Not sure if it needs to be in core.

I mean can't plugins just add their classes to it themselves, even with a hook there is no way to make plugin use it.

It is possible I have no idea what i am talking about, or misunderstand what you are trying to suggest.
NEW: SA Admin Toolbar Plugin | View All My Plugins
- Shawn A aka Tablatronix
Reply
#5
My suggestion is to eliminate the need to hard-code the include statements in the plugin files altogether (so developers no longer need to worry about the order in which the classes are loaded).

5.3 supports __autoload and spl_autoload_register. If a plugin developer implements them themselves (outside of the core), then there is still the problem that the autoloader functions do not get added to the autoload queue until later in the runtime (i.e. after the initialization).

I need to experiment, but this might work:

PHP Code:
add_hook('index-pretemplate''spl_autoload_register', array('my_autoloader')); 

*edit*

Figured out how to do it (with your help, shawn). These are only necessary for the plugin developer:

PHP Code:
add_action('common''spl_autoload_register', array('my_autoloader'));

...

function 
my_autoloader($class) {
  
$file GSPLUGINPATH basename(__FILE__'.php') . '/' $class '.class.php';
  if (
file_exists($file)) include($file);


'my_autoloader' then loads all classes for their plugin dynamically (didn't seem to work for the hook 'index-pretemplate', which I found slightly strange).

I suppose (if you wanted) you could condense that registration line to add_action('autoload', 'my_autoloader'), but its functionality is reflected in the above code.
Reply
#6
The plugin system could call an auto load register just like it does register plugin. Now instead of including file they still have to register the classes, of course most plugins should be including their classes in global scope anyway so the common hook still works. All classes should be available, auto load or not.
NEW: SA Admin Toolbar Plugin | View All My Plugins
- Shawn A aka Tablatronix
Reply
#7
Edited the example above; works with autoloading as desired. No need for a separate autoload register (the calls to the common hook essentially form that).

Quote:All classes should be available, auto load or not.

If done statically, the order needs to ensure that any dependencies exist at the time the include function is called, and any time a new class is created, said static list needs to be appended. The autoloading example removes the need to do this.
Reply
#8
The auto loader will have to register before common probably.

Although i still don't get the dependencies order issues, loading a class does not execute anything does it?
Dependencies are irrelevant until you actually use a class or a constructor runs.

Am I wrong?

Aside from extending one of course.
NEW: SA Admin Toolbar Plugin | View All My Plugins
- Shawn A aka Tablatronix
Reply
#9
Why even use a hook? Just add your classes to the auto loader right off.
NEW: SA Admin Toolbar Plugin | View All My Plugins
- Shawn A aka Tablatronix
Reply
#10
ill continue to think about this, my concentration is shot this week
NEW: SA Admin Toolbar Plugin | View All My Plugins
- Shawn A aka Tablatronix
Reply
#11
Did some more experimentation and you're right - you can simply use the autoloader off of the bat in the pluginname.php file.

PHP Code:
function my_autoloader($class) { ... }
spl_autoload_register('my_autoloader'); 

This works simultaneously for the front and back-end without the need for any hooks. When adding new classes, there is no longer a need to manage the series of includes lists (wherever they might be).

You've already solved it shawn; one less thing for you to think about :-P

Quote:loading a class does not execute anything does it?

In coding supplementary Matrix plugins, there was an issue on Ubuntu that plugins were loaded in reverse alphabetical order, so the order of the dependencies was completely buggered (e.g. Matrix CUsers initialization would take place before plain Matrix init) though again, I'm not sure if that also comes down to where/when certain plugin hooks were used). Most of that came down to the fact that those dependencies weren't loaded dynamically. This could solve those problems, though.
Reply




Users browsing this thread: 1 Guest(s)