Re: Making PEAR2 Portable

From: Date: Tue, 11 Sep 2007 18:35:55 +0000
Subject: Re: Making PEAR2 Portable
References: 1 2  Groups: php.pear.dev 
Request: Send a blank email to pear-dev+get-47995@lists.php.net to get a copy of this message
Greg: Thanks for your response. Thanks also for your seemingly infinite patience for explaining and defending the PEAR2 proposal. After rereading your reply, and some of this semi-infinite thread, I think I finally get the point: Removing "require_once" from the source code separates the problem of handling file dependencies from the code. As a result, it becomes possible to construct multiple ways of handling dependencies for different contexts, without modifying PEAR2 class source files. I'm convinced that this separation is simply a matter of good design. As such, there
is in fact intentionally no standard way to load files in PEAR2, but two possible ways of doing it: 1) include PEAR2_Autoload.php and then simply use PEAR2 classes without thinking about where they came from 2) write a customized loader script that includes all needed files manually.
The second way is a lot more work, but will be worth it to performance-hungry site admins.
Okay, got it. I hadn't understood that autoload was irreparably slow. Autoload implementation -----------------------
Perhaps I'm missing something, but don't see the point of having the PEAR2_Autoload() function try to define the magic __autoload() function internally, as done in the current svn implementation. If the PEAR2_Autoload function will normally be called only from within an __autoload() function, then an __autoload() function must necessarily be defined before PEAR2_Autoload() is called.
The point is to provide something with which absolute beginners can add 1 line of code to their apps and simply start using PEAR2 packages.
Sorry, but I'm still missing something. It seems to me that the minimal addition to user code is actually two lines: include 'pathto/PEAR2/Autoload.php' function __autoload($class) { return PEAR2_Autoload($class); } A two line addition is fine, and preferable to my proposal to put the second line in a separate file. My confusion arises from the fact that the only way the PEAR2:: Autoload function will ever be called is if it is called internally by a user-defined __autoload function, or registered by spl_autoload. That's why it seemed to me that is is pointless to try to redefine __autoload within PEAR2::Autoload, or have the PEAR2::Autoload function register itself with spl_autoload -- the fact that the PEAR2::Autoload function was called means that the php interpreter already knows to use it as the autoload function. This has to be set up correctly outside the function. What am I getting wrong?
The current PEAR2_Autoload makes no assumptions about include_path, but in fact sets it up if it isn't there, perhaps you're looking at an outdated version?
It still seems to me that the current autoload implementation depends on include_path being set correctly, in the following sense: The path that it uses to try to find a class file is simply $filename = str_replace('_', '/', $class) . '.php'. This path will allow the file to be opened only if the include path contains the PEAR2 root directory. If the attempt to open this file fails, it looks like the function throws an exception, and thus will never gets to the code where it tries to fix the include path. I agree, however, that all of this is immaterial to the underlying point of whether 'require_once' should be allowed, or whether PEAR2 will be more easily portable than PEAR: The standard autoload implementation can be tweaked, and a user can rewrite it at will. Once you get rid of 'require_once' in the source files, you give developers the freedom to handle dependencies however they want, without modifying PEAR class files. Loading Scripts --------------- Regarding the other proposed method, in which the PEAR developer writes a loading script, I'd like to clarify what a standard as-distributed script would look like. You'd like these scripts to work correctly when a user loads multiple PEAR packages, which may have overlapping dependencies. The easiest way to resolve the problem of overlapping dependencies would be to have the script for loading a package be a series of 'require_once' statements that load all of the files required by that package. Is this what you have in mind? If so, I agree that this would still be an improvement over the current situation. The dreaded 'require_once' statements would have been moved out of the class source files, and could be written to avoid checks that would be redundant even for the use of a single package. They would also be easier to locate and analyze, allowing those with a need for speed to easily combine scripts for several packages and remove redundant includes. Is this the concept? Or is the current proposal to provide only a standard autoload implementation and a list of file dependencies for each package, and let users write their own loading scripts from scratch? Thanks once more for your patience with such questions. -David
ii) For user that prefer to define a custom __autoload function: Give examples of how to call the PEAR2::autoload() function from within a more complicated user defined __autoload() function.
You mean like: if (PEAR2_Autoload($class)) return true;? Anyone who is in the process of customizing an autoload will have the technical know-how to do this, or to simply add these lines of code to their own __autoload:
    if (substr($class, 0, 6) === 'PEAR2_') {
        $fp = @fopen(str_replace('_', '/', $class) . '.php', 'r', true);
        if ($fp) {
            fclose($fp);
            require str_replace('_', '/', $class) . '.php';
            return true;
        }
    }
iii) For a user that prefers spl_autoload_register : Explain how to register the PEAR2::Autoload function. It would be up to the user to use the spl autoload stack in a way that avoids conflicts between autoloader implementations used by different libraries or packages.
This is explained in http://php.net/spl_autoload_register I'm not sure it is wise for us to duplicate documentation, but a link to the PHP documentation would not hurt.
This way, PEAR2 supports __autoload() and spl_autoload_register equally well. If this solution were accepted, you would also remove the code in the current PEAR2_Autoload that tries to reset the include_path - the whole goal would be to make the include_path irrelevant for the functioning of the autoloader. Comments? Anything obviously wrong?
Just that I think the point of PEAR2_Autoload() may not have been obvious enough - to provide a convenient one-liner for accessing all PEAR2 packages. Your comments did prompt some changes to the autoload implementation: 1) after loading the file that should contain the class, an extra check is added to ensure that the class indeed exists, and an exception is thrown if this is not the case to assist in debugging. 2) if SPL is loaded, spl_autoload_functions is checked for the presence of PEAR2_Autoload, and is registered. if __autoload exists, it is also registered if no spl_autoload stack was active. 3) all global variables used are prepended with a bunch of ____ to make sure they don't conflict with any that may exist in the user code, and are unset at the end of the file. http://svn.pear.php.net/wsvn/PEARSVN/Pyrus/trunk/src/Autoload.php?op=file Thanks, Greg
-- !-------------------------------------------------------------------! ! David Morse email: morse@cems.umn.edu ! ! Dept of Chem Eng & Mat Sci phone: (612)625-0167 ! ! University of Minnesota ! ! Minneapolis, MN 55455 ! !-------------------------------------------------------------------!

« previous php.pear.dev (#47995) next »