rfc:splclassloader
Differences
This shows you the differences between two versions of the page.
Both sides previous revisionPrevious revisionNext revision | Previous revisionNext revisionBoth sides next revision | ||
rfc:splclassloader [2011/11/08 13:30] – Added better examples guilhermeblanco | rfc:splclassloader [2012/06/29 06:52] – laruence | ||
---|---|---|---|
Line 77: | Line 77: | ||
| | ||
/** | /** | ||
- | | + | |
* | * | ||
* @param integer $mode Autoloader work mode. | * @param integer $mode Autoloader work mode. | ||
*/ | */ | ||
- | public function | + | public function |
| | ||
/** | /** | ||
Line 145: | Line 145: | ||
<code php> | <code php> | ||
- | $classLoader = new \SplClassLoader(\SplClassLoader:: | + | $classLoader = new \SplClassLoader(); |
+ | $classLoader-> | ||
$classLoader-> | $classLoader-> | ||
$classLoader-> | $classLoader-> | ||
+ | $classLoader-> | ||
+ | </ | ||
+ | |||
+ | Autoloading in debug mode: | ||
+ | |||
+ | <code php> | ||
+ | $classLoader = new \SplClassLoader(); | ||
+ | $classLoader-> | ||
+ | $classLoader-> | ||
+ | $classLoader-> | ||
$classLoader-> | $classLoader-> | ||
</ | </ | ||
Line 177: | Line 188: | ||
The following class is a sample SplClassLoader implementation that can load your classes if you follow the autoloader interoperability standards proposed above. It is the current recommended way to load PHP 5.3 classes that follow these standards. | The following class is a sample SplClassLoader implementation that can load your classes if you follow the autoloader interoperability standards proposed above. It is the current recommended way to load PHP 5.3 classes that follow these standards. | ||
- | |||
- | > NOTE: This implementation is not the proposed final. It requires two updates: | ||
- | > * Multiple paths per namespace | ||
- | > * Silent mode | ||
<code php> | <code php> | ||
- | <?php | ||
- | |||
/** | /** | ||
* SplClassLoader implementation that implements the technical interoperability | * SplClassLoader implementation that implements the technical interoperability | ||
* standards for PHP 5.3 namespaces and class names. | * standards for PHP 5.3 namespaces and class names. | ||
* | * | ||
- | | + | |
* | * | ||
- | | + | * Example |
- | * // Doctrine\Common namespace. | + | |
- | * $classLoader = new SplClassLoader(' | + | |
- | * $classLoader-> | + | |
* | * | ||
+ | | ||
+ | * | ||
+ | | ||
+ | | ||
+ | * | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | * | ||
+ | | ||
+ | | ||
+ | * | ||
+ | | ||
+ | | ||
+ | * | ||
+ | | ||
+ | | ||
+ | * | ||
+ | | ||
+ | | ||
+ | * | ||
+ | | ||
+ | | ||
+ | * | ||
+ | * @author Guilherme Blanco < | ||
* @author Jonathan H. Wage < | * @author Jonathan H. Wage < | ||
* @author Roman S. Borschel < | * @author Roman S. Borschel < | ||
Line 202: | Line 230: | ||
* @author Fabien Potencier < | * @author Fabien Potencier < | ||
*/ | */ | ||
- | class SplClassLoader | + | class SplClassLoader |
{ | { | ||
- | private $_fileExtension | + | |
- | private $_namespace; | + | * @var string |
- | private $_includePath; | + | */ |
- | private $_namespaceSeparator | + | |
+ | |||
+ | /** | ||
+ | * @var boolean | ||
+ | */ | ||
+ | private $includePathLookup = false; | ||
+ | |||
+ | /** | ||
+ | * @var array | ||
+ | */ | ||
+ | private $resources = array(); | ||
+ | |||
+ | /** | ||
+ | * @var integer | ||
+ | */ | ||
+ | private $mode = self:: | ||
/** | /** | ||
- | | + | |
- | * specified namespace. | + | |
- | * | + | |
- | | + | |
*/ | */ | ||
- | public function | + | public function |
{ | { | ||
- | | + | if ($mode & self:: |
- | $this->_includePath | + | throw new \InvalidArgumentException( |
+ | sprintf(' | ||
+ | ); | ||
+ | } | ||
+ | | ||
+ | $this->mode = $mode; | ||
} | } | ||
+ | |||
/** | /** | ||
- | | + | |
* | * | ||
- | * @param string $sep The separator to use. | + | * @param string $fileExtension |
*/ | */ | ||
- | public function | + | public function |
{ | { | ||
- | $this->_namespaceSeparator | + | $this->fileExtension |
} | } | ||
+ | |||
/** | /** | ||
- | | + | |
* | * | ||
- | * @return | + | * @return |
*/ | */ | ||
- | public function | + | public function |
{ | { | ||
- | return $this->_namespaceSeparator; | + | return $this->fileExtension; |
} | } | ||
+ | |||
/** | /** | ||
- | | + | |
* | * | ||
- | * @param | + | * @param |
*/ | */ | ||
- | public function | + | public function |
{ | { | ||
- | $this->_includePath | + | $this->includePathLookup |
} | } | ||
+ | |||
/** | /** | ||
* Gets the base include path for all class files in the namespace of this class loader. | * Gets the base include path for all class files in the namespace of this class loader. | ||
* | * | ||
- | * @return | + | * @return |
*/ | */ | ||
- | public function | + | public function |
{ | { | ||
- | return $this->_includePath; | + | return $this->includePathLookup; |
} | } | ||
+ | |||
/** | /** | ||
- | | + | |
- | * | + | |
- | | + | |
*/ | */ | ||
- | public function | + | public function |
{ | { | ||
- | $this-> | + | |
} | } | ||
+ | |||
/** | /** | ||
- | | + | |
- | * | + | |
- | | + | |
*/ | */ | ||
- | public function | + | public function |
{ | { | ||
- | | + | |
} | } | ||
+ | | ||
/** | /** | ||
- | | + | |
*/ | */ | ||
- | public function | + | public function |
{ | { | ||
- | | + | $this-> |
} | } | ||
+ | | ||
/** | /** | ||
- | | + | |
*/ | */ | ||
- | public function | + | public function |
{ | { | ||
- | | + | |
+ | |||
+ | switch (true) { | ||
+ | case ($this->mode & self:: | ||
+ | if ($resourceAbsolutePath !== false) { | ||
+ | require $resourceAbsolutePath; | ||
+ | } | ||
+ | break; | ||
+ | |||
+ | case ($this-> | ||
+ | default: | ||
+ | require $resourceAbsolutePath; | ||
+ | break; | ||
+ | } | ||
+ | |||
+ | if ($this-> | ||
+ | throw new \RuntimeException( | ||
+ | sprintf('Autoloader expected resource " | ||
+ | | ||
+ | } | ||
} | } | ||
+ | | ||
/** | /** | ||
- | | + | |
* | * | ||
- | * @param string $className The name of the class to load. | + | * @params |
- | * @return | + | * |
+ | * @return | ||
*/ | */ | ||
- | | + | |
{ | { | ||
- | | + | |
- | $fileName = ''; | + | |
- | $namespace = ''; | + | foreach |
- | if (false !== ($lastNsPos = strripos($className, $this-> | + | if (strpos($resourceName, $resource) !== 0) { |
- | $namespace | + | |
- | | + | |
- | $fileName = str_replace($this-> | + | |
} | } | ||
- | $fileName .= str_replace(' | + | |
- | + | foreach ($resourcesPath as $resourcePath) { | |
- | | + | $resourceAbsolutePath |
+ | |||
+ | if (is_file($resourceAbsolutePath)) { | ||
+ | return | ||
+ | } | ||
+ | | ||
+ | } | ||
+ | |||
+ | if ($this->includePathLookup && ($resourceAbsolutePath = stream_resolve_include_path($resourceRelativePath)) | ||
+ | return | ||
} | } | ||
+ | | ||
+ | return false; | ||
+ | } | ||
+ | | ||
+ | /** | ||
+ | * Transform resource name into its relative resource path representation. | ||
+ | * | ||
+ | * @params string $resourceName | ||
+ | * | ||
+ | * @return string Resource relative path. | ||
+ | */ | ||
+ | private function getResourceRelativePath($resourceName) | ||
+ | { | ||
+ | // We always work with FQCN in this context | ||
+ | $resourceName = ltrim($resourceName, | ||
+ | $resourcePath = ''; | ||
+ | | ||
+ | if (($lastNamespacePosition = strrpos($resourceName, | ||
+ | // Namespaced resource name | ||
+ | $resourceNamespace = substr($resourceName, | ||
+ | $resourceName | ||
+ | $resourcePath | ||
+ | } | ||
+ | | ||
+ | return $resourcePath . str_replace(' | ||
+ | } | ||
+ | | ||
+ | /** | ||
+ | * Check if resource is declared in user space. | ||
+ | * | ||
+ | * @params string $resourceName | ||
+ | * | ||
+ | * @return boolean | ||
+ | */ | ||
+ | private function isResourceDeclared($resourceName) | ||
+ | { | ||
+ | return class_exists($resourceName, | ||
+ | || interface_exists($resourceName, | ||
+ | || (function_exists(' | ||
} | } | ||
} | } | ||
</ | </ | ||
- | ===== Example usage ===== | + | If any interested wants to customize the public methods, like caching through APC to reduce I/O, it should be possible |
- | + | ||
- | <code php> | + | |
- | $classLoader = new SplClassLoader(\SplClassLoader:: | + | |
- | $classLoader-> | + | |
- | $classLoader-> | + | |
- | ' | + | |
- | array('/ | + | |
- | ); // Namespace style | + | |
- | $classLoader-> | + | |
- | $classLoader-> | + | |
- | </ | + | |
===== Proposal and Patch ===== | ===== Proposal and Patch ===== | ||
Line 344: | Line 440: | ||
Main purpose of this proposal is to support both PEAR style directory organization and also Namespace directory organization. | Main purpose of this proposal is to support both PEAR style directory organization and also Namespace directory organization. | ||
- | ===== Implementation extension | + | ===== Changelog |
- | According to new threads in php-standards list, it seems all derived implementations have included these extensions to original support: | + | * 2011-11-09 Christian Kaps: Update examples to use the new interface(setMode) |
- | * Multiple paths per namespace | + | * 2011-11-08 Guilherme Blanco: Removed constructor prototype and created setMode. |
- | * Silent mode as a flag | + | * 2011-11-08 Guilherme Blanco: Updated SplClassLoader implementation. |
- | + | ||
- | This turns the RFC specification incompatible with current patch. Patch is going to be updated as soon as voting ends. | + | |
- | + | ||
- | ===== Changelog ===== | + | |
* 2011-11-07 Guilherme Blanco: Expanded extended rules. | * 2011-11-07 Guilherme Blanco: Expanded extended rules. | ||
* 2011-10-25 David Coallier: Added the new SPL patch information and feature request link. | * 2011-10-25 David Coallier: Added the new SPL patch information and feature request link. | ||
Line 358: | Line 450: | ||
* 2010-03-22 Guilherme Blanco: Initial RFC creation. | * 2010-03-22 Guilherme Blanco: Initial RFC creation. | ||
+ | ===== Comments ===== | ||
+ | * laruence : I have already got a similar loader implemented in Yaf, called Yaf_Loader, you can found the source here: [[yaf_loader][http:// |
rfc/splclassloader.txt · Last modified: 2017/09/22 13:28 by 127.0.0.1