åå空éã¨autoloadãæ¨æºçãªClassLoaderã®å®è£ (#phpadvent2010)
ã£ã¦ãã¨ã§ãã¢ããã³ãã«ã¬ã³ãã¼ãåã£ã¦ããã®ã§æ¸ãã¾ãããªã«æ¸ãããè¿·ãã¾ããããã¨ãããããæè¿èªåã§ãçé¢ç®ã«ä½¿ãå§ããPHP 5.3åãã®ClassLoaderã¨åå空éã«ã¤ãã¦ã®è©±ã§ãã
ä¸ã®ä¸çã«ããã¶ããããããã¯PHP 5.3ã ãããçãªæµãããã¦ããã®ã§ãåå空éã®åºåãã¨ããã£ã¬ã¯ããªæ§æããã¡ã¤ã«åãã¯ã©ã¹åãªã©ãããããæ¸ããªãã©ããããã ãï¼ã£ã¦ã¨ããã«ã¤ãã¦ãããããã¦ããã¾ãã
PHP Standards Working Group
第1åã®ã¢ãã³PHPåå¼·ä¼ã§ãid:Fivestarãçºè¡¨ããããã«ãSymfonyãªã©ã®éçºè ãéã¾ã£ã¦ããã®ãããªå 容ãPHPçéã§ã¡ããã¨åã決ãã¦æ¨æºã£ã½ãããããã£ã¦è©±ããã¦ãããPHP Standards Working Groupã¨ããã°ã«ã¼ããããã¾ãã(æè¿ããã¾åãããªããª)
ãã®ã°ã«ã¼ãã§è°è«ãã¾ã¨ã¾ã£ã¦ãããã®ã«ãPSR-0 Final Proposal ãããããã®ä¸ã§ãåå空éã®ä½¿ãæ¹ã»ã¯ã©ã¹åã»ãã£ã¬ã¯ããªã®åºåãã¯ããããããã¨ããæè¦ãã¾ã¨ã¾ã£ã¦ã¾ãã*1
ä¾ããããã¨ã以ä¸ã®ãããªæãã
- \Doctrine\Common\IsolatedClassLoader => /path/to/project/lib/vendor/Doctrine/Common/IsolatedClassLoader.php
- \Symfony\Core\Request => /path/to/project/lib/vendor/Symfony/Core/Request.php
- \Zend\Acl => /path/to/project/lib/vendor/Zend/Acl.php
- \Zend\Mail\Message => /path/to/project/lib/vendor/Zend/Mail/Message.php
ã¡ãªã¿ã«ãã®ãã¼ã¸ã¯id:hnwããã翻訳ããã¦ãã¾ãã
SplClassLoader ã使ã£ã¦ã¿ããï¼
ã§ãæ¬é¡ãæ¨æºçãªåå空éã¨ã¯ã©ã¹åãªã©ã®å½åè¦åã決ã¾ãã°ãæ¨æºçãªAutoloadã¯ã©ã¹ãä½ããããã£ã¦ãã¨ã§ä½ãããã®ããSplClassLoaderã§ããSPLã£ã¦ååãä»ãã¦ããã©ãå¥ã«çµã¿è¾¼ã¿ã§ããªãããPHPçã«æ¨æºã«ãªã£ã¦ããããã§ããªãã®ã§ããææ¡ãã¬ãã«ã®ãã®ã§ãããSymfonyãããããã¼ã¹ã«ClassLoaderããã£ã¦ããããã¾ãå®è³ªæ¨æºçãªãã®ã§ããã¨èãã¦ããã£ã¦åé¡ãªãã§ãã
ã£ã¦ãã¨ã§ãããã使ã£ã¦ã¿ã¾ãããã
æ¨æºçãªãã£ã¬ã¯ããªæ§æã¨ã¯ã©ã¹ã®ãã¡ã¤ã«ãç¨æ
ä»åã¯ã以ä¸ã®ãããªæãã§ä½ã£ã¦ã¿ã¾ããã
% tree . |-- Hoge | |-- Hogege.php | `-- Hogera | `-- Aho.php |-- SplClassLoader.php |-- entry_point.php `-- libs `-- vendors `-- Fuga `-- Foo.php
entry_point.php ãå®éã«ã©ã¤ãã©ãªã使ãå´ã®ãã¡ã¤ã«ãHoge 㨠Fuga ããèªã¿è¾¼ã¾ããå´ã®ã©ã¤ãã©ãªãã¡ã¤ã«ã ã¨æ³å®ããFuga ã¯ã©ããå¤ãªã¨ãã«ãã£ã¬ã¯ããªããããã®ã ã¨ãã¾ããã¾ããããããæ§æã ã¯ã¨æãã¾ããAho.php Hogera.php Foo.php ã«ã¯å®éã«ã¯ã©ã¹ãå®ç¾©ããã¦ãã¦ãã¨ããããã³ã³ã¹ãã©ã¯ã¿ãå¼ã°ããã¨èªåèªèº«ã®åå空éã¨ã¯ã©ã¹åãåºåããããã«ãã¦ããã¾ãã
ä¾ãã°æ¬¡ã®ãããªæãï¼
<?php namespace Hoge\Hogera; class Aho { public function __construct() { echo __CLASS__, PHP_EOL; } }
å®éã«ä½¿ã£ã¦ã¿ã
entry_point.php ã§ã¯ã次ã®ãã register() ã¡ã½ãããå¼ã³åºããåå空éã¨ãã£ã¬ã¯ããªã®ã«ã¼ããæå®ãããã®ãç»é²ãã¾ãã
<?php require 'SplClassLoader.php'; $class_loader_hoge = new SplClassLoader('Hoge', __DIR__); $class_loader_hoge->register(); $class_loader_fuga = new SplClassLoader('Fuga', __DIR__ . '/libs/vendors'); $class_loader_fuga->register(); $a = new Hoge\Hogege(); $b = new Hoge\Hogera\Aho(); $c = new Fuga\Foo();
ãã®åºåã¯ã
Hoge\Hogege Hoge\Hogera\Aho Fuga\Foo
ã¨ãªãã¾ãã
æ£ããHogeãFugaã®åå空éã®ã¯ã©ã¹ãèªã¿è¾¼ã¾ãã¾ãããã
ClassLoaderã®åãã追ã£ã¦ã¿ã
ClassLoader ã®å®è£ ã¯ç°¡åã§ãä¸è¨ã§èª¬æããã¨ã
ç»é²ãããåå空éã¨ãã¹ãçµåã㦠\ ã / ã«å¤ã㦠.php ãä»ãã
ããã ãã§ãã
ã§ã¯ã
$class_loader_hoge = new SplClassLoader('Hoge', __DIR__); $class_loader_hoge->register();
ãã®è¨å®ã§Autoloadã®è¨å®ããã
$b = new Hoge\Hogera\Aho();
ãã使ã£ãã¨ãã«ãã©ãèªã¿è¾¼ã¾ãããã¨ããã¨ã
<?php // 以ä¸ã¯ãSplClassLoaderã®ãã¼ãé¨åã®å®è£ ã public function loadClass($className) { if (null === $this->_namespace || $this->_namespace.$this->_namespaceSeparator === substr($className, 0, strlen($this->_namespace.$this->_namespaceSeparator))) { $fileName = ''; $namespace = ''; if (false !== ($lastNsPos = strripos($className, $this->_namespaceSeparator))) { // åå空éåºåããè¦ã¤ããã°ããããæå¾ã®åå空éåºåã以ä¸ãã¯ã©ã¹åã¨ãã¦ã // ã¯ã©ã¹åã¨åå空éã«å解ãã $namespace = substr($className, 0, $lastNsPos); // => "Hoge\Hogera" $className = substr($className, $lastNsPos + 1); // => "Aho" $fileName = str_replace($this->_namespaceSeparator, DIRECTORY_SEPARATOR, $namespace) . DIRECTORY_SEPARATOR; // åå空éã®åºåãæå "\" ã "/" ã«å¤æãã¦ããã¹åã«ãã // => "Hoge/Hogera/" } $fileName .= str_replace('_', DIRECTORY_SEPARATOR, $className) . $this->_fileExtension; // ã¯ã©ã¹åã®ã¢ã³ãã¼ã¹ã³ã¢ "_" ã "/" ã«å¤æãã¦ãæ¡å¼µåãã¤ãã // ããã¦ãããããã¹åã«çµåããããããã¡ã¤ã«åã¨ãã // => "Hoge/Hogera/Aho.php" require ($this->_includePath !== null ? $this->_includePath . DIRECTORY_SEPARATOR : '') . $fileName; // æå¾ã«ãè¨å®ãã¦ããã¤ã³ã¯ã«ã¼ããã¹ã«ãã¡ã¤ã«åãçµåãã¦requireãã // => "/home/sotarok/tmp/splclassloader/Hoge/Hogera/Aho.php" } }
ã ããããããªãããã§ãSplClassLoaderã®ã³ã³ã¹ãã©ã¯ã¿ã«æå®ããã¤ã³ã¯ã«ã¼ããã¹ã¨ããã以ä¸ã®ãã¹ãåå空éãå«ãã ã¯ã©ã¹åã¨ãããã³ã°ãããã¯ã©ã¹ãèªã¿è¾¼ã¾ãã¾ããå®ã«åç´ã§ããã
ã¾ãã¾ã§ã使ãããã©ã»ã»ã»
å®éã«ã¯ãããã¡ãã£ã¨ã«ã¼ãºã«ä½¿ãããã£ãã®ã§ãregisterNamespace()ã¨ãã®staticã¡ã½ãããå®ç¾©ãã¦ä½¿ã£ã¦ã¾ãã*2
ããããã¨ã
<?php ClassLoader::registerNamespace('Hoge', '/path/to/Hoge'); ClassLoader::registerNamespace('Fuga', '/path/to/Fuga');
ãªãã¦ãããã§ã«ã¼ãºã«ä½¿ãã¦ç´ æµã§ãã
ã¨ããããã§
ãããããã¨æã£ã¦åå空éã使ãã¯ãããã¨ãã¾ã ã¾ã ãã¦ãã¦ãå ±æããã¦ããªãã¦ï¼ããã§ãåºã¦ããã»ãã§ããï¼æ©ããã¨ãå¤ãã¨æãã¾ãããåèã«ãªãã°å¹¸ãã§ãã
ã¢ããã³ãã«ã¬ã³ãã¼ã®ããã³ã¯ slumbers99 ããã«ã渡ããã¾ãï¼
PHP 5.3ã®è©±ãã¡ããã¨èª¬æãã¦ãããパーフェクトPHPããããããï¼
*1:ãããããGoogle Groupsã£ã¦ãã¼ã¸æ©è½ããµãã¼ãããªããªãã£ã½ããã©ããã®ã¸ãã®ãã¼ã¸ã¯ã©ããªããã ãããã»ã»ã»
*2:file_exists使ãã¨statãçºçãããããã³ã¹ãçã«ãªã¼ã£ã¦ãã¤ãããã¾ããããã¾ããErrorExceptioné£ã°ãããã«ãããã¨ãããããããã¾ãããå人çã«ã¯ããã§ãã£ããããããã