I've been looking into how to best organise my libraries/classes recently and I'm yet to come up with a satisfactory solution. That and it would just be a whole lot cleaner to write $xyz = new XyzImplementation()
than $xyz = $this->load->library('xyz_implementation')
. And it only gets worse with multiple instances, it seems pretty geared toward using libraries/models as singletons.
Why doesn't CodeIgniter just use spl_autoload_register
or __autoload()
itself? I know that CI knows where it's class files are so doesn't necessarily need to go looking each time a class is instantiated. Is it just a speed thing? And/or keeping it lightweight? If that's the case then I want to know what method is best to use to give CI this functionality, i.e. $xyz = new XyzImplementation()
.
I've tried HMVC but don't like the fact that it basically scraps the core CI_Loader
and reimplements each function. I've gotta wonder what would happen if the contents of the core methods was to change.. I guess anyone using HMVC would have to wait for it to be patched (or patch it themselves on github)
I've come up with my own solution tonight but I'm not sure it's all that efficient. It basically uses directory_map
to find a class of the corresponding name (e.g. XyzImplementation.php
) anywhere below APPPATH
. Sounds horrible, right? Once it's found XyzImplementation.php
once, it's location is cached in a file and just looked up next time around so once the site/app has been through a bit of testing there's no reason why every instantiation won't be a look-up.
Does that sound like a half decent solution? Assume that find_class_path
returns the full relative path to the found class file using a recursive directory look-up.
// ignore system classes
if('CI' === substr($name, 0, 2) || 'MY' === substr($name, 0, 2))
{
return;
}
// read cache
$cache = array();
$cache_file = APPPATH.'cache/abracadabra.php';
$class_in_cache = false;
if(file_exists($cache_file))
{
$cache_contents = file_get_contents($cache_file);
if(!empty($cache_contents))
{
$cache = unserialize($cache_contents);
if(array_key_exists($name, $cache))
{
$class_in_cache = true;
include_once($cache[$name]);
}
}
}
// class not in cache, find it in application
if(!$class_in_cache)
{
// TODO be more restrictive than APPP开发者_StackOverflow中文版ATH
$class_path = find_class_path($name, APPPATH);
// TODO handle case where a class isn't found
$cache[$name] = $class_path;
file_put_contents($cache_file, serialize($cache)); // add to cache
include_once $class_path;
}
// instantiate
if(class_exists($name)) // so as to not instantiate interfaces
{
return new $name;
}
Not being a developer of CodeIgniter, I can't speak of why they don't use __autoload
or spl_autoload_register
. However, I can think of a couple reasons why I might not:
Some opcode caches do not support autoloading. For a product that will be used on a variety of servers in production, that would be an alienating mistake and could lead to a substantial performance hit and among others, speed is a key attraction to CodeIgniter.
Using the $this->load->library('authentication') syntax would allow a more efficient differentiation between what exactly is being loaded, be it a helper, library, model, etc and I think makes your code easier to read.
As for your implementation of autoloading classes, let's say that all your used classes are cached in your cache file. You're adding an extra IO request and uneeded memory usage to every class instantiation you perform. It's that kind of overhead that can come back to get you if you're thinking that your application will ever reach enterprise level. It's good to think about these things before you get big, it'll save you heartache and money later.
To be honest, I have found nothing messy about the way CodeIgniter handles class instantiation. I agree that using the CodeIgniter loader is more geared to singleton-esque usage, however if you needed to instantiate an instance of a class, say a person object, then why not just include it like you would any normal PHP class? In fact, if you're instantiating for reasons pertaining to your models, why not just use a great ORM framework?
精彩评论