note 61565 deleted from language.oop5.autoload by felipe
| From: | felipe@php.net | Date: | Mon, 24 Mar 2008 22:34:08 +0000 |
| Subject: | note 61565 deleted from language.oop5.autoload by felipe | ||
| References: | 1 | Groups: | php.notes |
| Request: | Send a blank email to php-notes+get-137497@lists.php.net to get a copy of this message | ||
Note Submitter: unspammable-iain at iaindooley dot com
----
in response to the post by UNSPAMMABLEkai at kaiundina dot de, i have another interesting
implementation of the __autoload() system.
i have all my classes in their own file, where ThisClassName would be in the file
this_class_name.class.php (Ruby inspired :-)
i really like having all class dependencies at the top of the class file, because you can tell at a
glance what packages/classes a particular class uses/depends on, but this meant big loading times
for huge class heirarchies, even if all those classes were not being used.
so i created my own require function that uses a serialised array of include paths, and then an
__autoload() function that will get the required included path when it is needed _only_. this also
allows for nice and liberal directory structures.
Here is the file with all the implementation in it:
<?
@$contents = file_get_contents('managed_code/includes.php');
if($contents)
$include_paths = unserialize($contents);
else
$include_paths = array();
function __autoload($class)
{
if($path = rsIncludePath($class))
require_once($path);
else
{
echo('You need to call rsRequire() before using a class: '.$class);
debug_print_backtrace();
}
}
function rsIncludePath($class)
{
global $include_paths;
$ret = '';
if(isset($include_paths[$class]))
$ret = $include_paths[$class];
return $ret;
}
function rsRequire($class,$required = true)
{
global $include_paths;
$classname = rsClassName($class);
$path = preg_replace('/\./','/',rsClasstoFile($class));
$path .= '.class.php';
if((!file_exists('packages/'.$path)))
{
echo('couldn\'t load package: '.$class.'<br /><br />
');
if($required)
debug_print_backtrace();
}
else
{
$path = 'packages/'.$path;
if(isset($include_paths[$classname]))
{
if($include_paths[$classname]!=$path)
{
$include_paths[$classname] = $path;
rsPersist();
}
}
else
{
$include_paths[$classname] = $path;
rsPersist();
}
}
}
function rsClassName($class)
{
$split = preg_split('/\./',$class);
$class_name = $split[count($split)-1];
return $class_name;
}
function rsPersist()
{
global $include_paths;
$data = serialize($include_paths);
file_put_contents('managed_code/includes.php',$data);
}
?>
Now here is a class file:
<?
rsRequire('package.name.SomeBaseClass');
rsRequire('package.name.MightNotBeUsed');
class ThisClass extends SomeBaseClass
{
/**ALL MY CODE***/
}
?>
the class file for MightNotBeUsed would only be included if it was actually used in the class code.
Also, notice that the above method is quite efficient because it only unserialises the array of
include paths once, and will only reserialise the array in the case that it is a new include path,
or the include path has changed. Also notice that this is 'session safe', meaning if you
register a session object and then your application dies, you will not get class non-existing errors
the next time you run it because the include paths are serialised as they are added. Enjoy!