psr ps2 estándares codestyle php autoload psr-0

ps2 - PHP: el autocargador más liviano que cumple con psr-0



psr-* (7)

Tengo una pequeña aplicación para la que necesito un autoloader. Podría usar fácilmente el cargador de clases symfony2 pero parece una exageración.

¿Hay un cargador automático psr-0 extremadamente liviano y estable por ahí?


El documento de especificación PSR-0 tiene una función de cargador automático compatible ejemplar que ya es bastante corta:

function autoload($className) { $className = ltrim($className, ''//'); $fileName = ''''; $namespace = ''''; if ($lastNsPos = strripos($className, ''//')) { $namespace = substr($className, 0, $lastNsPos); $className = substr($className, $lastNsPos + 1); $fileName = str_replace(''//', DIRECTORY_SEPARATOR, $namespace) . DIRECTORY_SEPARATOR; } $fileName .= str_replace(''_'', DIRECTORY_SEPARATOR, $className) . ''.php''; require $fileName; }

Su uso es bastante sencillo:

spl_autoload_register(''autoload'');

El inconveniente es que necesita configurar los directorios base sobre los que funciona con la directiva include_path . Para admitir un PSR-0 híbrido, los cargadores automáticos se apoyaron en la semántica de SPL, el siguiente es compatible con las extensiones de ruta y spl de carga automática:

$spl_autoload_register_psr0 = function ($extensions = null) { $callback = function ($className, $extensions = null) { if (!preg_match(''~^[a-z0-9//_]{2,}$~i'', $className)) { return; } null !== $extensions || $extensions = spl_autoload_extensions(); $extensions = array_map(''trim'', explode('','', $extensions)); $dirs = array_map(''realpath'', explode(PATH_SEPARATOR, get_include_path())); $classStub = strtr($className, array(''_'' => ''/'', ''//' => ''/'')); foreach ($dirs as $dir) { foreach ($extensions as $extension) { $file = sprintf(''%s/%s%s'', $dir, $classStub, $extension); if (!is_readable($file)) { continue; } include $file; return; } } }; return spl_autoload_register($callback); };

El componente ClassLoader de Symfony2 tiene la ventaja de permitir más configuraciones aquí. Puedes instalarlo fácilmente a través de Pear o Composer ( symfony / class-loader en Packagist ). Es un componente en sí mismo que es usado por muchos y bastante bien probado y soportado.


Esta no es una respuesta directa a la pregunta, pero descubrí que las respuestas anteriores funcionaron muy bien en scripts de PHP independientes, pero causaron problemas cuando se usaron en ciertos marcos, como Joomla.

Para cualquier persona que use Joomla, resulta que ya hay un cargador automático compatible integrado en el marco, por lo que no necesitará usar las funciones anteriores. En ese caso, simplemente llame a JLoader :: registerNamespace () .... por ejemplo:

JLoader::registerNamespace(''Solarium'', JPATH_LIBRARIES . DS . ''solarium-3.2.0'' . DS . ''library'');



Un equivalente exacto de la respuesta que proporcionó @hakre , pero más breve:

function autoload($class) { $path = null; if (($namespace = strrpos($class = ltrim($class, ''//'), ''//')) !== false) { $path .= strtr(substr($class, 0, ++$namespace), ''//', ''/''); } require($path . strtr(substr($class, $namespace), ''_'', ''/'') . ''.php''); }

También puede establecer el directorio base cambiando $path = null; a otro valor, o simplemente hacer esto:

$paths = array ( __DIR__ . ''/vendor/'', __DIR__ . ''/vendor/phunction/phunction.php'', ); foreach ($paths as $path) { if (is_dir($path) === true) { spl_autoload_register(function ($class) use ($path) { if (($namespace = strrpos($class = ltrim($class, ''//'), ''//')) !== false) { $path .= strtr(substr($class, 0, ++$namespace), ''//', ''/''); } require($path . strtr(substr($class, $namespace), ''_'', ''/'') . ''.php''); }); } else if (is_file($path) === true) { require($path); } }


Usted pregunta extremadamente ligero, hagámoslo;)

Timothy Boronczyk escribió un bonito autocargador de SPL mínimo: http://zaemis.blogspot.fr/2012/05/writing-minimal-psr-0-autoloader.html

Condensé el código así:

function autoload1( $class ) { preg_match(''/^(.+)?([^////]+)$/U'', ltrim( $class, ''//' ), $match ) ); require str_replace( ''//', ''/'', $match[ 1 ] ) . str_replace( [ ''//', ''_'' ], ''/'', $match[ 2 ] ) . ''.php''; }

Luego compare (versiones mínimas de) este [autoload3] con el corto código @Alix Axel [autoload4]:

function autoload3($c){preg_match(''/^(.+)?([^////]+)$/U'',ltrim($c,''//'),$m);require str_replace(''//',''/'',$m[1]).str_replace([''//',''_''],''/'',$m[2]).''.php'';} function autoload4($c){require (($n=strrpos($c=ltrim($c,''//'),''//'))!==false?str_replace(''//',''/'',substr($c,0,++$n)):null).str_replace(''_'',''/'',substr($c,$n)).''.php'';}

autoload3 es el más corto!

Vamos a usar un autocargador estable y extremadamente ligero (175b!):

<?php spl_autoload_register(function ($c){preg_match(''/^(.+)?([^////]+)$/U'',ltrim($c,''//'),$m);require str_replace(''//',''/'',$m[1]).str_replace([''//',''_''],''/'',$m[2]).''.php'';});

Tal vez estoy loco pero tú pediste extremo, ¿no?

EDITAR: Gracias a Alix Axel, he acortado el código (¡solo 100b!) Y he usado include en lugar de require en caso de que tengas varias estrategias de carga automática para libs antiguas (y luego varios autoloader en la pila spl autoload stack ...).

<?php spl_autoload_register(function($c){@include preg_replace(''#///|_(?!.+///)#'',''/'',$c).''.php'';});

Si quieres hacerlo más corto / mejor, por favor usa esta gist .



function autoload($fullClassName) { $name_elems = explode(''//', $fullClassName); require __DIR__.DIRECTORY_SEPARATOR.implode(DIRECTORY_SEPARATOR, $name_elems).''.php''; }

Esto incluso admite cosas como: $ transformerContstraint = new / Recurr / Transformer / Constraint / AfterConstraint (new DateTime ());

Solo póngalo en /vendor/Recurr/Transformer/Constraint/AfterConstraint.php