Page 1 of 2
Is autoload the best practice in PHP now?
Posted: Thu Dec 03, 2009 1:38 am
by Christopher
Is using autoload (SPL's I assume) rather than require_once()/include_once() in libraries considered the best practice now? It certainly cleans up library code that is one class per file (with dependencies). And is the PHP Group's performance tuning heading toward making autoload the best choice?
Re: Is autoload the best practice in PHP now?
Posted: Thu Dec 03, 2009 5:34 am
by wei
I say yes, unless you really need to squeeze the last drop out of PHP. Although if you very likely to know before hand how many files needs to be included before runtime for the most common cases, it can help if these files are combined into 1 file (via some automated calculation).
Re: Is autoload the best practice in PHP now?
Posted: Thu Dec 03, 2009 6:25 am
by josh
require statements are a smell to me because there's lots of legitimate reasons I would want to modify the file structure (like merging a large framework into one big file with 1,000s of classes in it, to reduce flippant abuse of my expensive hardware

). No point in wasting dev time figuring out includes when people end up stripping them out anyways.
requires_once I will use from
time to time, in unit tests, or in cases where a file is not a class and is not easily autoloadable (ex. Zend style controllers, by default, get put in a controllers directory which doesn't match their class path. so require is needed there, unless you rework your file structure to something original)
Re: Is autoload the best practice in PHP now?
Posted: Thu Dec 03, 2009 12:57 pm
by John Cartwright
My only issue with using an auto loader and frameworks is if the framework is completely dependent on auto-loading, then using reusable components will not be possible without also including an auto-loader. However, in the scope of the framework itself, the benefits (lazy loading, less clutter, etc) outweigh the costs.
Re: Is autoload the best practice in PHP now?
Posted: Thu Dec 03, 2009 2:49 pm
by Christopher
Are there any hybrid solutions that solve the stand-alone component problem? For example if you do:
Code: Select all
if (! class_exists('Foo_Bar', true)) include 'Foo/Bar.php';
The class_exists() will trigger the autoload if defined. But wrapping the include() in an if defeats some of PHP's optimizations I think.
Re: Is autoload the best practice in PHP now?
Posted: Thu Dec 03, 2009 3:43 pm
by allspiritseve
John Cartwright wrote:if the framework is completely dependent on auto-loading, then using reusable components will not be possible without also including an auto-loader.
That's not entirely true, is it? You could just include the files needed before you use them. That's what I've been doing for testing the Skeleton ORM, since it doesn't have inline includes and we don't have an autoloader set up for tests (as far as I know).
Re: Is autoload the best practice in PHP now?
Posted: Thu Dec 03, 2009 3:58 pm
by John Cartwright
allspiritseve wrote:John Cartwright wrote:if the framework is completely dependent on auto-loading, then using reusable components will not be possible without also including an auto-loader.
That's not entirely true, is it? You could just include the files needed before you use them. That's what I've been doing for testing the Skeleton ORM, since it doesn't have inline includes and we don't have an autoloader set up for tests (as far as I know).
In all circumstances, no it is not true. However, when these reusable components in turn use other classes, then problems will arise. Using the Zend Framework as an example (lets forget the fact they use inline includes for a second), each component will likely have a specific exception class. Exception classes are of course belong in their own file, and without being included manually/autoloaded, the component would throw a fatal error.
Re: Is autoload the best practice in PHP now?
Posted: Thu Dec 03, 2009 4:42 pm
by josh
Well, the programmer ought to be used to having to litter their code with includes if theyre not using auto loading.
I think if you don't put require statements you will definitely cut your audience, but it can be it's own form of technical debt. For instance now are you going to run your unit tests with and without the require statements stripped just to double check? And you have to figure out which requires are needed, and remember to remove them when they are no longer required (extra steps when re-factoring)
Re: Is autoload the best practice in PHP now?
Posted: Thu Dec 03, 2009 6:15 pm
by Christopher
The other possibility for releasing components from a larger framework is that the all of the stand-alone component's files could be put into a single file when released separately.
Any comments on wrapping include/require in a if (! class_exists() ) {
Re: Is autoload the best practice in PHP now?
Posted: Thu Dec 03, 2009 8:06 pm
by daedalus__
i can't answer the oq but i like autoload i think its a really neat feature.
then again a lot of other languages have their analogues to include.
Re: Is autoload the best practice in PHP now?
Posted: Thu Dec 03, 2009 8:42 pm
by allspiritseve
arborint wrote:Any comments on wrapping include/require in a if (! class_exists() ) {
Seems like even more clutter than before.
I thought I remembered reading something about SwiftMailer having an autoloader built in that would work as long as you included one file. Is there any reason something like that wouldn't work for Skeleton (and any other standalone library)?
Re: Is autoload the best practice in PHP now?
Posted: Thu Dec 03, 2009 9:18 pm
by alex.barylski
thought I remembered reading something about SwiftMailer having an autoloader built in that would work as long as you included one file. Is there any reason something like that wouldn't work for Skeleton (and any other standalone library)?
Thats how I do it. If you include the Spectra_System class (which you pretty much always will) it's autoloader automatically registers itself and will include any Spectra_X classes. The tricky part was making it work with other autoloaders, which would probably be the case when people use a framework, along side their favorite libraries (Swift, AdoDB, Smarty whatever).
Re: Is autoload the best practice in PHP now?
Posted: Fri Dec 04, 2009 8:15 am
by josh
allspiritseve wrote:
Seems like even more clutter than before.
agreed.
I thought I remembered reading something about SwiftMailer having an autoloader built in that would work as long as you included one file. Is there any reason something like that wouldn't work for Skeleton (and any other standalone library)?
exactly, I think theres 2 includes. One sets up the auto loader, the other is just a big list of calls to a dependency injection system that includes every class in the library. I choose to use neither, I just added that path to my existing auto loader, so I felt like I was not restricted in any way using Swift Mailer, I had 3 possible ways to handle the including
Here's how it works
Code: Select all
Swift_DependencyContainer::getInstance()
-> register('transport.failover')
-> asNewInstanceOf('Swift_Transport_FailoverTransport')
In dependency_maps.php he has some scripts that wire things up in this dependency container.
Then before he use's a dependency he does this:
Code: Select all
call_user_func_array(
array($this, 'Swift_Transport_FailoverTransport::__construct'),
Swift_DependencyContainer::getInstance()
->createDependenciesFor('transport.failover')
);
This goes and looks up the "transport.failover" key in a map of classes. It finds all the classes a Transport_Failover needs to be instantiated. (dependency injection),
so there are never any if( !class_exists()) calls or includes/requires. I think it may have to use auto loading to achieve this though, haven't looked into it too much
Edit:
Ok yeah here's the auto loader:
Code: Select all
/*
* This file is part of SwiftMailer.
* (c) 2004-2009 Chris Corbyn
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
/**
* General utility class in Swift Mailer, not to be instantiated.
*
* @package Swift
*
* @author Chris Corbyn
*/
abstract class Swift
{
/** Swift Mailer Version number generated during dist release process */
const VERSION = '4.0.5';
/**
* Internal autoloader for spl_autoload_register().
*
* @param string $class
*/
public static function autoload($class)
{
//Don't interfere with other autoloaders
if (0 !== strpos($class, 'Swift'))
{
return false;
}
$path = dirname(__FILE__).'/'.str_replace('_', '/', $class).'.php';
if (!file_exists($path))
{
return false;
}
require_once $path;
}
/**
* Configure autoloading using Swift Mailer.
*
* This is designed to play nicely with other autoloaders.
*/
public static function registerAutoload()
{
spl_autoload_register(array('Swift', 'autoload'));
}
}
He put a comment by the part where it is "designed to play nicely with other auto loaders", If I remember I never used this file, I just added his path to my existing auto loader and instantiated the class I needed.
Re: Is autoload the best practice in PHP now?
Posted: Wed Dec 09, 2009 12:30 pm
by Christopher
So it seem like, following Josh's comments, that if you follow PEAR naming conventions then it is usually trivial for people to add a path to their autoloaders. But what about if they don't have an autoloader? What do people consider the cleanest and easiest ways to initialize autoloading. Is just including a script in the top level directory of the library the preferred solution?
Re: Is autoload the best practice in PHP now?
Posted: Wed Dec 09, 2009 4:41 pm
by josh
I think that a default auto loader should be included with the distribution, as long as care is taken to follow "common auto loader convention". Usually converting _ to / suffices, and nothing more or less.
Chris' implementation could be used as a standard, I like it. It accounts for things I didnt think of too:
Code: Select all
public static function autoload($class)
{
//Don't interfere with other autoloaders
if (0 !== strpos($class, 'Swift'))
{
return false;
}
$path = dirname(__FILE__).'/'.str_replace('_', '/', $class).'.php';
if (!file_exists($path))
{
return false;
}
require_once $path;
}