ClassLoader
Gepost door Jasper Lammertink op 05-03-2009 20:33.
Een autoloader met caching.
Roep de ClassLoader aan aan het begin van elk script waarin je hem wilt gebruiken.
<?php
require_once 'pad/naar/je/ClassLoader.php';
// root van je applicatie
define('PATH_ROOT', realpath(dirname(__FILE__).'/../../..').'/');
// wel of geen caching gebruiken
ClassLoader::useCaching(true);
// overige instellingen die altijd nodig zijn
// ** het is denk ik wel duidelijk wat de methods vertellen aan de ClassLoader
ClassLoader::setCachePath(PATH_ROOT.'cache/cache.php');
ClassLoader::addClassPath(PATH_ROOT.'php/classes/');
ClassLoader::excludeFolder('/$lib^/');
ClassLoader::init();
?>
Opmerkingen/suggesties/bugs graag melden.
Bestanden van dit script
index.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 | <?php
class ClassLoader
{
private static $use_caching;
private static $cache_path;
private static $class_paths = array();
private static $exclude_patterns = array();
private static $class_map = array();
private static $duplicates;
public static function init()
{
self::getClassMap();
if (self::$duplicates)
{
exit;
}
spl_autoload_register(array('ClassLoader', 'autoload'));
}
public static function autoload($class_name)
{
if (isset(self::$class_map[$class_name]))
{
require_once self::$class_map[$class_name];
}
}
public static function useCaching($bool)
{
self::$use_caching = $bool;
}
public static function setCachePath($filename)
{
self::$cache_path = $filename;
}
public static function addClassPath($directory)
{
self::$class_paths[] = $directory;
}
public static function excludeFolder($regex)
{
self::$exclude_patterns[] = $regex;
}
private static function getClassMap()
{
if (self::$use_caching && file_exists(self::$cache_path))
{
self::$class_map = include self::$cache_path;
}
else
{
foreach (self::$class_paths as $class_path)
{
self::$class_map = array_merge(self::$class_map, self::scanDirectory($class_path));
}
if (self::$use_caching && !self::$duplicates)
{
self::writeCache();
}
}
}
private static function scanDirectory($directory)
{
$class_map = array();
foreach (scandir($directory) as $filename)
{
if ($filename != '.' && $filename != '..')
{
if (is_dir($directory.$filename))
{
$exclude = false;
foreach (self::$exclude_patterns as $exclude_pattern)
{
if (preg_match($exclude_pattern, $filename))
{
$exclude = true;
}
}
if (!$exclude)
{
$class_map = array_merge($class_map, self::scanDirectory($directory.$filename.'/'));
}
}
else
{
$class_name = str_replace('.php', '', $filename);
if (preg_match('/[class|interface] '.$class_name.'/', file_get_contents($directory.$filename)))
{
if (!isset(self::$class_map[$class_name]) && !isset($class_map[$class_name]))
{
$class_map[$class_name] = $directory.$filename;
}
else
{
self::$duplicates = true;
echo 'ClassLoader : <font color="#FF0000">duplicate</font> : <font color="#009900">'.$class_name.'</font> ( <font color="#0000FF">'.$directory.$filename.'</font> )<br />';
}
}
}
}
}
return $class_map;
}
private static function writeCache()
{
ksort(self::$class_map);
$contents = '<?php'."\n".'return array(';
$i = 0;
foreach (self::$class_map as $class_name => $filename)
{
if ($i > 0)
{
$contents .= ',';
}
$contents .= "\n".' \''.$class_name.'\' => \''.$filename.'\'';
$i ++;
}
$contents .= "\n".');'."\n".'?>';
$handle = fopen(self::$cache_path, 'w');
fwrite($handle, $contents);
fclose($handle);
}
}
?> |
Commentaar
05-03-2009 19:38
Een exit als er al een autoloader gedefineerd is, is rond uit vies. Dat wil je niet.
Je kan nu ook niet makkelijk meerdere libraries tegelijk gebruiken + applicaties met Poor Man Namespacing zijn zo niet te gebruiken.
1 2 3 | Post hier de source-code van je script. Alle informatie tussen <? ... ?> en <?php ... ?> zal automatisch worden getoond in color-coding.
Let op! Het is niet de bedoeling om hier een link naar je website te plaatsen. Post hier gewoon de code, veel simpeler, sneller en meer kans dat het blijft staan. |
05-03-2009 20:13
Ik kan even geen logica vinden dat alles static is en een functie (init) niet.
1 2 3 | Post hier de source-code van je script. Alle informatie tussen <? ... ?> en <?php ... ?> zal automatisch worden getoond in color-coding.
Let op! Het is niet de bedoeling om hier een link naar je website te plaatsen. Post hier gewoon de code, veel simpeler, sneller en meer kans dat het blijft staan. |
05-03-2009 20:24
@Tom Janssen
Dat moet natuurlijk ook een static zijn (bugje)
@iltar van der Berg
De autoloader is nog helemaal niet gedefinieerd als de exit wordt uitgevoerd.
En al zou die gedefinieerd zijn voor de exit dan maakt dat nog niets uit.
Die exit wordt ook alleen uitgevoerd als er een error optreed (duplicates).
1 2 3 | Post hier de source-code van je script. Alle informatie tussen <? ... ?> en <?php ... ?> zal automatisch worden getoond in color-coding.
Let op! Het is niet de bedoeling om hier een link naar je website te plaatsen. Post hier gewoon de code, veel simpeler, sneller en meer kans dat het blijft staan. |
06-03-2009 11:32
Het duurde even maar ik heb em aan de praat...
kort gezegd, het is wellicht wel leuk voor jouzelf, maar omdat het een bepaalde (in mijn ogen ongewenste) structuur en naamgeving afdwingt, vraag ik me af wat het toepassingsniveau ervan is.
Daarnaast ben je wat vergeten te vermelden...
in de functie scandirectory zit een pregmatch -zie (1)-, waardoor je een bepaalde naamgeving afdwingt. Misschien even vermelden, ik had het niet gezien en vroeg me af waarom er niks gebeurde...
Dan nog een bug:
Ik krijg duplicates waarschuwingen terwijl ik 100% zeker weet dat het geen duplicates zijn. Het zijn verschillende Exception classes in verschillende folders met een verschillende _class_name, maar dezelfde Filename (Exception.php).
Hieruit blijkt dat je niet de classname pakt, maar de bestandsnaam....
Wat dan wel weer raar is, is dat ik nog een aantal exceptions erin heb zitten, en dat die worden overgeslagen, die zijn namelijk gewoon overschreven (alleen de laatste Exception bestaat nog).
En idd. Poor Mans Namespacing is er niet bij deze class...
11-03-2009 11:13
> De autoloader is nog helemaal niet gedefinieerd als de exit wordt uitgevoerd.
> En al zou die gedefinieerd zijn voor de exit dan maakt dat nog niets uit.
> Die exit wordt ook alleen uitgevoerd als er een error optreed (duplicates).
Dan moet je een error geven, niet een witte pagina.
1 2 3 | Post hier de source-code van je script. Alle informatie tussen <? ... ?> en <?php ... ?> zal automatisch worden getoond in color-coding.
Let op! Het is niet de bedoeling om hier een link naar je website te plaatsen. Post hier gewoon de code, veel simpeler, sneller en meer kans dat het blijft staan. |
11-03-2009 11:30
>> De autoloader is nog helemaal niet gedefinieerd als de exit wordt uitgevoerd.
>> En al zou die gedefinieerd zijn voor de exit dan maakt dat nog niets uit.
>> Die exit wordt ook alleen uitgevoerd als er een error optreed (duplicates).
> Dan moet je een error geven, niet een witte pagina.
Als je even verder in de code kijkt zie je dat ie dat ook doet.
Als je een Exception wil gooien moet je dat zelf even aanpassen.
Hij geeft dus geen witte pagina :-)
1 2 3 | Post hier de source-code van je script. Alle informatie tussen <? ... ?> en <?php ... ?> zal automatisch worden getoond in color-coding.
Let op! Het is niet de bedoeling om hier een link naar je website te plaatsen. Post hier gewoon de code, veel simpeler, sneller en meer kans dat het blijft staan. |
24-04-2009 18:46
Met dit script, kun je makkelijk de OS laten zien van de gebruiker die de website bezoekt.
Je kan het aanroepen via:
$client_os = client_os(); print 'Uw computer draait op ' . $client_os . '<br />';
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 | <?php
function client_os()
{
if (eregi("(win|windows)[ ]*((nt)*[ /]*([0-9]+(.?[0-9]+))*)", $_SERVER["HTTP_USER_AGENT"]))
{
if (eregi("(win|windows)[ ](95)", $_SERVER["HTTP_USER_AGENT"]))
{
return "Windows 95";
}
else if (eregi("(win|windows)[ ](98)", $_SERVER["HTTP_USER_AGENT"]))
{
return "Windows 98";
}
else if (eregi("(win|windows)[ ](9x)[ ](4.90)", $_SERVER["HTTP_USER_AGENT"]))
{
return "Windows ME";
}
else if (eregi("(win|windows)[ ](NT)", $_SERVER["HTTP_USER_AGENT"]))
{
if (eregi("(win|windows)[ ](NT)[ ](5.1)", $_SERVER["HTTP_USER_AGENT"]))
{
return "Windows XP";
}
else if (eregi("(win|windows)[ ](NT)[ ](5.0)", $_SERVER["HTTP_USER_AGENT"]))
{
return "Windows 2000";
}
else if (eregi("(win|windows)[ ](NT)", $_SERVER["HTTP_USER_AGENT"]))
{
return "Windows NT";
}
}
else
{
return "Windows";
}
}
else if (stristr($_SERVER["HTTP_USER_AGENT"], "linux"))
{
return "Linux";
}
else if (stristr($_SERVER["HTTP_USER_AGENT"], "unix"))
{
return "Unix";
}
else if (stristr($_SERVER["HTTP_USER_AGENT"], "mac"))
{
return "MacOS";
}
else if (stristr($_SERVER["HTTP_USER_AGENT"], "ppc"))
{
return "MacOS";
}
else if (stristr($_SERVER["HTTP_USER_AGENT"], "HP"))
{
return "HPuX";
}
else if (stristr($_SERVER["HTTP_USER_AGENT"], "sunos"))
{
return "SunOS";
}
else
{
return "Unknown";
}
}
?> |