Welcome! » Log In » Create A New Profile

should make use of __autoload in PHP5

Posted by Grady Kuhnline 
Grady Kuhnline
should make use of __autoload in PHP5
August 05, 2007 02:55PM

http://us.php.net/manual/en/language.oop5.autoload.php

This function makes the insane inclusion scheme found in many PHP projects obsolete. The way this is usually implemented is through a hash array that looks like this:

<?php
return array(
    'HTMLPurifier' => 'HTMLPurifier.php',
    'HTMLPurifier_AttrDef' => 'HTMLPurifier/AttrDef.php',
    ...
);
?>

Then you can easily provide instructions and methods for including HTMLPurifier in an existing __autoload scheme.

<?php
function __autoload ($className)
{
    // try to load HTMLPurifier
    if (strpos($className, 'HTMLPurifier_') === 0)
    {
       HTMLPurifier_Base::autoload($className); 
    }
    // try to load your own class
    else
    {
        // my personal autoload scheme for my project
    }
}
?>

You can find an overly complicated version of this in the ezComponents library: http://ez.no/doc/components/view/2007.1.1/(file)/Base/ezcBase.html

Re: should make use of __autoload in PHP5
August 06, 2007 02:06AM

I am very well aware of autoload. While we continue to have support for PHP4, it's too much trouble to migrate HTML Purifier over to this system: our current policy is code for PHP 4, then tweak to make it run in PHP 5 E_STRICT. This prevents too much rewriting from going on between the two branches, and even then there are interesting difficulties.

Once we drop PHP 4 support around December, I'll consider it. However, I realize that some users may not want to bother with this sort of thing, so a regular include scheme will probably be the baseline.

Grady Kuhnline
Re: should make use of __autoload in PHP5
August 13, 2007 01:42PM

I'm sensitive to your need to support a large community. However you should strongly consider moving to the autoload method. If your user is already using PHP5, there is no barrier to using __autoload(). Even more important, it will make your project dependencies much easier to manage. If you've ever worked on a project with __autoload you'd have to agree it is a much more elegant solution to the traditional include scheme.

I was able to convert HTMLPurifier to use this method in just a few minutes with a search and replace. I was foiled however, by the way that defined variables are set up and the way in which objects are passed between classes. It was a timing issue. In the traditional method, the dependencies are included before our class is defined. In the autoload method, the dependencies are loaded as they are requested which is after the class is defined. This caused the define() and the config calls at the top of many of the files to be called late and break the entire system.

I found this to be unfortunate and disappointing. I think a minor redesign of the classes to utilize static variables, class constants and so on would alleviate much of the problem.

Re: should make use of __autoload in PHP5
August 13, 2007 08:25PM

I have no problem with redesigning some facets of HTML Purifier to make it play more nicely with __autoload. In fact, this would be extremely beneficial for a "standalone" version of HTML Purifier which consists of all the includes smooshed together in one big file.

However, I have not ever used __autoload before, so it is difficult for me to appropriately address the issue.

Grady Kuhnline
Re: should make use of __autoload in PHP5
August 14, 2007 06:59PM

Please let me know what I can do to help you address this issue. I would be available to offer support in designing the approach HTMLPurifier could use to implement __autoload. It is surprisingly simple.

Please email me if you are interested in my input. I may even be able to loan some development resources if you'd like.

The calls to HTMLPurifier_ConfigSchema::define at the top of most of the files is the big killer here. The way that the config schema is passed through the inheritance chain is not very friendly to this process.

Re: should make use of __autoload in PHP5
August 16, 2007 01:54AM

Hi, thank you for the offer of help. I understand in basic terms how __autoload() works: it's the implementation details that will be bugger. Here are a few questions:

  • How would you prefer to add HTML Purifier's autoloading capabilities to your own __autoload() function?
  • Should HTML Purifier automatically define an __autoload() function if none is currently being used? What if the user decides to later add an __autoload() function?
  • Would you recommend centralizing ConfigSchema? The error-checking capabilities of the configuration object are, I believe, quite useful, but they cost performance.
  • There are certain areas in HTML Purifier where some reflection is used to dynamically include class files. Would you recommend unconditionally including the files, or some other method? A specific patch for these areas (URISchemeRegistry is a good place to start) would be fantastic.

And any other problems you can think of. Thanks for the help!

Grady Kuhnline
Re: should make use of __autoload in PHP5
August 28, 2007 09:47PM

1) My own __autoload function

function __autoload ($className)
{
    if ($className === 'HTMLPurifier_Base')
        include 'path/to/HTMLPurifier/HTMLPurifierBase.class.php';
    else if (strpos($className, 'HTMLPurifier') === 0)
        HTMLPurifier_Base::autoload($className);
    else
    {
        //My own project's autoinclude logic
    }
}

2) HTMLPurifier built in __autoload

if (!function_exists('__autoload'))
{
    function __autoload ($className)
    {
        HTMLPurifier_Base::autoload($className);
    }
}

3) About centralizing the ConfigSchema. I am not terribly aware of what the ConfigSchema does and what "centralizing" entails... but I would suggest rethinking the way that object is populated and the way it is shared.

I think this is similar to a static config class that all of the modules can work with. It would be best to simply always work with it as a static object instead of trying to pass it around to each object.

HTMLPurifier_ConfigSchema::setValue('key', 'value');
$value = HTMLPurifier_ConfigSchema::getValue('key');

I would also investigate removing the ConfigSchema object altogether in favor of PHP5 class constants. It looks like the ConfigSchema never really changes.

class MyObject
{
    const KEY = 'value';
}

4) In a perfect world, include or require would not appear in your code outside of the __autoload functions. Then you could remove all the logic for what files to include. If you need a class, it will magically appear.

KevBurnsJr
Re: should make use of __autoload in PHP5
September 16, 2007 11:55PM

I ran my own workaround for this.

	if($class == "HTMLPurifier") {
		
		require_once("lib/HTMLPurifier.auto.php");
		
	}
	else if(strstr($class, "HTMLPurifier")) {
		
		require_once("lib/".str_replace("_","/",$class).".php");
		
	}
	else switch($class) {
	
		...

Makes use of the fact that the class naming convention follows the directory structure.

Kudos :)

David Goodwin
Re: should make use of __autoload in PHP5
February 18, 2008 11:42AM

Hi,

Just to add my oar in...

My understanding is that reliance upon __autoload() is not good if performance is an issue, as classes become dynamically loaded (i.e. a cache can't predict what will be required... )

See also spl__autoload - which allows you to register multiple __autoload like functions, and not have a conflict with a.n.other project who also thought it was a good idea to have a function called __autoload... (i.e. you both do spl_autoload_register('my_function') or something of a similar name).

thanks David

Re: should make use of __autoload in PHP5
February 18, 2008 07:31PM

I'm already way ahead of you guys. :-D Trunk versions of HTML Purifier now use autoload by default. If you don't mind grabbing a nightly and testing it out, I would greatly appreciate it!

Matti
Re: should make use of __autoload in PHP5
March 11, 2008 11:09AM

Easy with overriding __autoload read this first.

http://fi.php.net/spl_autoload_register

Re: should make use of __autoload in PHP5
March 11, 2008 04:03PM

Actually, spl_autoload_register has been the subject of a lot of painful compatibility code. But yes, that's what we use. Check HTMLPurifier.autoload.php and HTMLPurifier/Bootstrap.php for info (in the trunk)

Sorry, you do not have permission to post/reply in this forum.