如何使用自动加载的PHP名称空间?

我尝试使用自动加载和命名空间时遇到此错误:

致命错误:10行中的/usr/local/www/apache22/data/public/php5.3/test.php中找不到类“Class1”

谁能告诉我我做错了什么?

这是我的代码:

Class1.php:

<?php namespace Person\Barnes\David { class Class1 { public function __construct() { echo __CLASS__; } } } ?> 

test.php的:

 <?php function __autoload($class) { require $class . '.php'; } use Person\Barnes\David; $class = new Class1(); ?> 

Class1不在全局范围内。

看下面的一个工作示例:

 <?php function __autoload($class) { $parts = explode('\\', $class); require end($parts) . '.php'; } use Person\Barnes\David as MyPerson; $class = new MyPerson\Class1(); 

编辑(2009-12-14):

为了澄清,我使用“use … as”是为了简化这个例子。

替代scheme如下:

 $class = new Person\Barnes\David\Class1(); 

要么

 use Person\Barnes\David\Class1; // ... $class = new Class1(); 

正如Pascal MARTIN所提到的,你应该用DIRECTORY_SEPARATORreplace'\',例如:

 $filename = BASE_PATH . DIRECTORY_SEPARATOR . str_replace('\\', DIRECTORY_SEPARATOR, $class) . '.php'; include($filename); 

此外,我会build议你重新组织的结构,使代码更具可读性。 这可能是一个替代scheme:

目录结构:

 ProjectRoot |- lib 

File: /ProjectRoot/lib/Person/Barnes/David/Class1.php

 <?php namespace Person\Barnes\David class Class1 { public function __construct() { echo __CLASS__; } } ?> 
  • 为您定义的每个名称空间创build子目录。

文件: /ProjectRoot/test.php

 define('BASE_PATH', realpath(dirname(__FILE__))); function my_autoloader($class) { $filename = BASE_PATH . '/lib/' . str_replace('\\', '/', $class) . '.php'; include($filename); } spl_autoload_register('my_autoloader'); use Person\Barnes\David as MyPerson; $class = new MyPerson\Class1(); 
  • 我使用php 5 recomendation自动加载器声明。 如果您仍然使用PHP 4,请将其replace为旧的语法:function __autoload($ class)

您的__autoload函数将收到完整的类名称,包括名称空间名称。

这意味着,在你的情况下, __autoload函数将会收到' Person\Barnes\David\Class1 ',而不是' Class1 '。

所以,你必须修改你自动加载的代码,来处理那种“更复杂”的名字; 一个经常使用的解决scheme是使用名称空间的“级别”级别的目录来组织文件,而在自动加载时,用DIRECTORY_SEPARATORreplace名称空间名称中的“ \ ”。

我做这样的事情:

 spl_autoload_register('AutoLoader'); function AutoLoader($className) { $file = str_replace('\\',DIRECTORY_SEPARATOR,$className); require_once 'classes' . DIRECTORY_SEPARATOR . $file . '.php'; //Make your own path, Might need to use Magics like ___DIR___ } 

我从Flysystemfind了这颗gem

 spl_autoload_register(function($class) { $prefix = 'League\\Flysystem\\'; if ( ! substr($class, 0, 17) === $prefix) { return; } $class = substr($class, strlen($prefix)); $location = __DIR__ . 'path/to/flysystem/src/' . str_replace('\\', '/', $class) . '.php'; if (is_file($location)) { require_once($location); } }); 

我发现自动加载函数只接收“完整的”类名 – 所有的名字空间都在它之前 – 在以下两种情况下:

 [a] $a = new The\Full\Namespace\CoolClass(); [b] use The\Full\Namespace as SomeNamespace; (at the top of your source file) followed by $a = new SomeNamespace\CoolClass(); 

我发现在以下情况下,自动加载函数不会收到完整的类名:

 [c] use The\Full\Namespace; (at the top of your source file) followed by $a = new CoolClass(); 

更新:[c]是一个错误,不是名称空间如何工作。 我可以报告,而不是[c],以下两种情况也适用:

 [d] use The\Full\Namespace; (at the top of your source file) followed by $a = new Namespace\CoolClass(); [e] use The\Full\Namespace\CoolClass; (at the top of your source file) followed by $a = new CoolClass(); 

希望这可以帮助。

有同样的问题,只是发现这一点:

当您创build与包含类的名称空间匹配的子文件夹结构时,您甚至不需要定义自动加载器。

  spl_autoload_extensions(".php"); // comma-separated list spl_autoload_register(); 

它像一个魅力工作

更多信息: http : //www.php.net/manual/en/function.spl-autoload-register.php#92514

编辑:这会导致Linux上的问题,因为反斜杠…看到这里的工作解决schemeimmeëmosol

命名空间自动加载在Windows下工作,但不在Linux上

使用有一个问题,虽然它是迄今为止最快的方法,它也期望所有的文件名都是小写的。

 spl_autoload_extensions(".php"); spl_autoload_register(); 

例如:

包含SomeSuperClass类的文件需要命名为someSuperclass.php,如果您的文件被命名为SomeSuperClass.php而不是Windows下的问题,则在使用像Linux这样的区分大小写的文件系统时,这是一个难题。

在你的代码中使用__autoload可能仍然适用于当前版本的PHP,但是期望这个特性将被弃用,并在将来被删除。

那么剩下什么select:

该版本将与PHP 5.3及以上版本兼容,允许文件名SomeSuperClass.php和somesuperclass.php。 如果您使用5.3.2或更高版本,则此自动加载器的工作速度会更快。

 <?php if ( function_exists ( 'stream_resolve_include_path' ) == false ) { function stream_resolve_include_path ( $filename ) { $paths = explode ( PATH_SEPARATOR, get_include_path () ); foreach ( $paths as $path ) { $path = realpath ( $path . PATH_SEPARATOR . $filename ); if ( $path ) { return $path; } } return false; } } spl_autoload_register ( function ( $className, $fileExtensions = null ) { $className = str_replace ( '_', '/', $className ); $className = str_replace ( '\\', '/', $className ); $file = stream_resolve_include_path ( $className . '.php' ); if ( $file === false ) { $file = stream_resolve_include_path ( strtolower ( $className . '.php' ) ); } if ( $file !== false ) { include $file; return true; } return false; }); 

我将为相对初学者投入我的两分钱,或者不想要一个简单的spl_autoload_register()设置,而不需要所有的理论:只需为每个类创build一个php文件,命名该php文件与您的类名相同,并保存类文件在你的PHP文件在相同的目录中,然后这将工作:

 spl_autoload_register(function ($class_name) { require_once dirname(__FILE__) . DIRECTORY_SEPARATOR . $class_name . '.php'; }); 

使用Googlesearch这个函数应该能够解决它的工作原理。 PS:我使用Linux,这在Linux上运行。 Windows的人应该先testing一下。

我最近发现tanerkuc的回答非常有帮助! 只是想补充说,使用strrpos() + substr()explode() + end()稍快:

 spl_autoload_register( function( $class ) { $pos = strrpos( $class, '\\' ); include ( $pos === false ? $class : substr( $class, $pos + 1 ) ).'.php'; }); 

https://thomashunter.name/blog/simple-php-namespace-friendly-autoloader-class/

你需要把你的类文件放到一个名为Classes的文件夹中,这个文件夹与你的PHP应用程序的入口点在同一个目录下。 如果类使用名称空间,名称空间将被转换为目录结构。 与许多其他自动加载器不同,下划线不会被转换为目录结构(PHP <5.3伪名称空间和PHP> = 5.3真实名称空间是很难的)。

 <?php class Autoloader { static public function loader($className) { $filename = "Classes/" . str_replace("\\", '/', $className) . ".php"; if (file_exists($filename)) { include($filename); if (class_exists($className)) { return TRUE; } } return FALSE; } } spl_autoload_register('Autoloader::loader'); 

你将要把下面的代码放到你的主PHP脚本(入口点)中:

 require_once("Classes/Autoloader.php"); 

这是一个目录布局的例子:

 index.php Classes/ Autoloader.php ClassA.php - class ClassA {} ClassB.php - class ClassB {} Business/ ClassC.php - namespace Business classC {} Deeper/ ClassD.php - namespace BusinessDeeper classD {}