Skip to content

Instantly share code, notes, and snippets.

@k-holy
Created January 31, 2012 01:15
Show Gist options
  • Save k-holy/1707998 to your computer and use it in GitHub Desktop.
Save k-holy/1707998 to your computer and use it in GitHub Desktop.
PSR-0対応Autoloader
<?php
namespace Acme;
require_once realpath(__DIR__ . '/vendor/k-holy/src/Holy/Loader.php');
// PHP 5.3 (using setter)
spl_autoload_register(\Holy\Loader::getInstance()
->set('Holy', realpath(__DIR__ . '/vendor/k-holy/src'))
->set('Acme', realpath(__DIR__ . '/app/src'))
, true, true);
<?php
namespace Acme;
require_once realpath(__DIR__ . '/vendor/k-holy/src/Holy/Loader.php');
// PHP5.4 Array short syntax
spl_autoload_register(\Holy\Loader::getInstance([
'Holy' => [realpath(__DIR__ . '/vendor/k-holy/src')],
'Acme' => [realpath(__DIR__ . '/app/src')],
]), true, true);
<?php
/**
* PHP versions 5
*
* @copyright 2011 k-holy <[email protected]>
* @author [email protected]
* @license http://www.opensource.org/licenses/mit-license.php The MIT License (MIT)
*/
namespace Holy;
/**
* Loader
*
* @author [email protected]
*/
class Loader
{
const FILE_EXTENSION = '.php';
const NAMESPACE_SEPARTOR= '\\';
protected $vendors = array();
protected function __construct(array $vendors = array())
{
$this->init($vendors);
}
public static function getInstance(array $vendors = array())
{
return new self($vendors);
}
public function __invoke($className)
{
return $this->load($className);
}
public function init(array $vendors = array())
{
$this->vendors = $vendors;
}
/**
* ベンダー名および設置パス、拡張子を設定します。
* @param string ベンダー名(namespace)
* @param string 設置パス
* @param string 拡張子
*/
public function set($name, $includeDir, $fileExtension=null)
{
$includeDir = rtrim($includeDir, '\\/');
if ('\\' === DIRECTORY_SEPARATOR) {
$includeDir = str_replace('/', '\\', $includeDir);
}
$this->vendors[$name] = array($includeDir, $fileExtension);
return $this;
}
/**
* 指定されたクラスのファイルを読み込みます。
* @param string クラス名
*/
public function load($className)
{
if (false === ($filePath = $this->findFile($className))) {
return false;
}
return require $filePath;
}
protected function findFile($className)
{
$baseName = ltrim($className, self::NAMESPACE_SEPARTOR);
$useNamespace = false;
if (false !== ($pos = strrpos($baseName, self::NAMESPACE_SEPARTOR))) {
$useNamespace = true;
$namespace = substr($baseName, 0, $pos);
$baseName = substr($baseName, $pos + 1);
$fileName = str_replace(self::NAMESPACE_SEPARTOR, DIRECTORY_SEPARATOR, $namespace)
. DIRECTORY_SEPARATOR . str_replace('_', DIRECTORY_SEPARATOR, $baseName);
} else {
$fileName = str_replace('_', DIRECTORY_SEPARATOR, $baseName);
}
$requirePath = null;
foreach ($this->vendors as $name => $info) {
$includeDir = $info[0];
$fileExtension = (isset($info[1])) ? $info[1] : self::FILE_EXTENSION;
if (0 === strpos(($useNamespace) ? $namespace : $baseName, $name)) {
$path = $includeDir . DIRECTORY_SEPARATOR . $fileName . $fileExtension;
if (file_exists($path)) {
$requirePath = $path;
break;
}
}
}
if (is_null($requirePath)) {
$requirePath = stream_resolve_include_path($fileName . self::FILE_EXTENSION);
}
return $requirePath;
}
}
<?php
namespace Holy\Tests;
use Holy\Loader;
/**
* LoaderTest
*
* @author [email protected]
*/
class LoaderTest extends \PHPUnit_Framework_TestCase
{
private $defaultLoaders = array();
private $defaultIncludePath = null;
private $loader = null;
public function setUp()
{
$this->defaultLoaders = spl_autoload_functions();
if (!is_array($this->defaultLoaders)) {
$this->defaultLoaders = array();
}
$this->defaultIncludePath = get_include_path();
$this->loader = Loader::getInstance();
$this->loader->init();
}
public function tearDown()
{
$loaders = spl_autoload_functions();
if (is_array($loaders)) {
foreach ($loaders as $loader) {
spl_autoload_unregister($loader);
}
}
if (is_array($this->defaultLoaders)) {
foreach ($this->defaultLoaders as $loader) {
spl_autoload_register($loader);
}
}
set_include_path($this->defaultIncludePath);
}
public function testCreateNewInstance()
{
$this->assertNotSame($this->loader, Loader::getInstance());
}
public function testLoadNamespacedClass()
{
$this->loader
->set('LoadSample', realpath(__DIR__ . '/LoaderTest/lib/vendor'))
->load('\LoadSample\Foo');
$this->assertInstanceOf('\LoadSample\Foo', new \LoadSample\Foo());
$this->loader->load('\LoadSample\Foo\Bar');
$this->assertInstanceOf('\LoadSample\Foo\Bar', new \LoadSample\Foo\Bar());
$this->loader->load('\LoadSample\Foo\Bar\Baz');
$this->assertInstanceOf('\LoadSample\Foo\Bar\Baz', new \LoadSample\Foo\Bar\Baz());
}
public function testloadLegacyClassWithDirectoryAndExtension()
{
$this->loader
->set('Smorty', realpath(__DIR__ . '/LoaderTest/lib/vendor/Smorty/libs'), '.class.php')
->load('Smorty');
$this->assertInstanceOf('\Smorty', new \Smorty());
}
public function testAutoloadLegacyClassInIncludePath()
{
set_include_path(realpath(__DIR__ . '/LoaderTest/include_path'));
$this->loader->load('\PearStyleClass_Example');
$this->assertInstanceOf('\PearStyleClass_Example', new \PearStyleClass_Example());
}
public function testAutoload()
{
$this->loader
->set('AutoloadSample', realpath(__DIR__ . '/LoaderTest/lib/vendor'))
->set('Smorty' , realpath(__DIR__ . '/LoaderTest/lib/vendor/Smorty/libs'), '.class.php');
spl_autoload_register(array($this->loader, 'load'), true, true);
set_include_path(realpath(__DIR__ . '/LoaderTest/include_path'));
$this->assertInstanceOf('\AutoloadSample\Foo', new \AutoloadSample\Foo());
$this->assertInstanceOf('\AutoloadSample\Foo\Bar', new \AutoloadSample\Foo\Bar());
$this->assertInstanceOf('\AutoloadSample\Foo\Bar\Baz', new \AutoloadSample\Foo\Bar\Baz());
$this->assertInstanceOf('\Smorty', new \Smorty());
$this->assertInstanceOf('\PearStyleClass_Example', new \PearStyleClass_Example());
}
public function testAutoloadByInvokeMagicMethod()
{
spl_autoload_register(Loader::getInstance(array(
'AutoloadSample' => array(realpath(__DIR__ . '/LoaderTest/lib/vendor')),
'Smorty' => array(realpath(__DIR__ . '/LoaderTest/lib/vendor/Smorty/libs'), '.class.php'),
)), true, true);
set_include_path(realpath(__DIR__ . '/LoaderTest/include_path'));
$this->assertInstanceOf('\AutoloadSample\Foo', new \AutoloadSample\Foo());
$this->assertInstanceOf('\AutoloadSample\Foo\Bar', new \AutoloadSample\Foo\Bar());
$this->assertInstanceOf('\AutoloadSample\Foo\Bar\Baz', new \AutoloadSample\Foo\Bar\Baz());
$this->assertInstanceOf('\Smorty', new \Smorty());
$this->assertInstanceOf('\PearStyleClass_Example', new \PearStyleClass_Example());
}
}
@k-holy
Copy link
Author

k-holy commented Jan 31, 2012

https://gist.github.com/1127033 ここからの改良。
やはりローダー自身がspl_autoload_register()するのはおかしいよね、ということでこうしました。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment