I get this error when I try to use autoload and namespaces:
当我尝试使用autoload和名称空间时,我得到了这个错误:
Fatal error: Class 'Class1' not found in /usr/local/www/apache22/data/public/php5.3/test.php on line 10
致命错误:类“Class1”没有在/usr/local/www/apache22/data/public/php5.3/test中找到php的地铁十号线
Can anyone tell me what I am doing wrong?
有人能告诉我我做错了什么吗?
Here is my code:
这是我的代码:
Class1.php:
Class1.php:
<?php
namespace Person\Barnes\David
{
class Class1
{
public function __construct()
{
echo __CLASS__;
}
}
}
?>
test.php:
test.php:
<?php
function __autoload($class)
{
require $class . '.php';
}
use Person\Barnes\David;
$class = new Class1();
?>
12 个解决方案
#1
104
Class1 is not in the global scope.
Class1不在全局范围内。
See below for a working example:
请参阅下面的工作示例:
<?php
function __autoload($class)
{
$parts = explode('\\', $class);
require end($parts) . '.php';
}
use Person\Barnes\David as MyPerson;
$class = new MyPerson\Class1();
Edit (2009-12-14):
编辑(2009-12-14):
Just to clarify, my usage of "use ... as" was to simplify the example.
只是为了澄清一下,我使用的“use…”as是为了简化例子。
The alternative was the following:
另一种选择是:
$class = new Person\Barnes\David\Class1();
or
或
use Person\Barnes\David\Class1;
// ...
$class = new Class1();
#2
22
As mentioned Pascal MARTIN, you should replace the '\' with DIRECTORY_SEPARATOR for example:
正如前面提到的Pascal MARTIN,您应该用DIRECTORY_SEPARATOR代替'\',例如:
$filename = BASE_PATH . DIRECTORY_SEPARATOR . str_replace('\\', DIRECTORY_SEPARATOR, $class) . '.php';
include($filename);
Also I would suggest you to reorganize the dirrectory structure, to make the code more readable. This could be an alternative:
我还建议您重新组织脏结构,使代码更可读。这可以是一个备选办法:
Directory structure:
目录结构:
ProjectRoot
|- lib
File: /ProjectRoot/lib/Person/Barnes/David/Class1.php
文件:/ ProjectRoot / lib /人/巴恩斯/大卫/ Class1.php
<?php
namespace Person\Barnes\David
class Class1
{
public function __construct()
{
echo __CLASS__;
}
}
?>
- Make the sub directory for each namespace you are defined.
- 为定义的每个名称空间创建子目录。
File: /ProjectRoot/test.php
文件:/ 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();
- I used php 5 recomendation for autoloader declaration. If you are still with PHP 4, replace it with the old syntax: function __autoload($class)
- 我使用php 5的recomendation来声明自动加载程序。如果您还在使用PHP 4,请使用旧语法替换它:function __autoload($class)
#3
15
Your __autoload
function will receive the full class-name, including the namespace name.
__autoload函数将接收完整的类名,包括名称空间名。
This means, in your case, the __autoload
function will receive 'Person\Barnes\David\Class1
', and not only 'Class1
'.
这意味着,在您的例子中,__autoload函数将接收“Person\Barnes\David\Class1”,而不仅仅是“Class1”。
So, you have to modify your autoloading code, to deal with that kind of "more-complicated" name ; a solution often used is to organize your files using one level of directory per "level" of namespaces, and, when autoloading, replace '\
' in the namespace name by DIRECTORY_SEPARATOR
.
因此,你必须修改你的自动读码,以处理那种“更复杂”的名字;通常使用的解决方案是使用每个名称空间“级别”的一个目录来组织文件,并且,当自动读取时,用DIRECTORY_SEPARATOR替换名称中的“\”。
#4
10
I do something like this:
我这样做:
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___
}
#5
3
I found this gem from Flysystem
我从Flysystem找到了这个宝石
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);
}
});
#6
3
I see that the autoload functions only receive the "full" classname - with all the namespaces preceeding it - in the following two cases:
我发现,autoload函数只接收“完整”类名——所有名称空间都在前面——在以下两种情况下:
[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();
I see that the autoload functions DO NOT receive the full classname in the following case:
我看到autoload函数在以下情况下不接收完整的类名:
[c] use The\Full\Namespace; (at the top of your source file) followed by $a = new CoolClass();
UPDATE: [c] is a mistake and isn't how namespaces work anyway. I can report that, instead of [c], the following two cases also work well:
更新:[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();
Hope this helps.
希望这个有帮助。
#7
1
had the same issue and just found this :
有同样的问题,刚刚发现:
When you create a subfolder structure matching the namespaces of the containing classes, you will never even have to define an autoloader.
当您创建与包含类的名称空间匹配的子文件夹结构时,您甚至不需要定义一个autoloader。
spl_autoload_extensions(".php"); // comma-separated list
spl_autoload_register();
It worked like a charm
它很有魅力
More info here : http://www.php.net/manual/en/function.spl-autoload-register.php#92514
更多信息:http://www.php.net/manual/en/function.spl-autoload-register.php#92514。
EDIT: this causes problem on Linux because of backslash... See here for working solution by immeëmosol
编辑:由于反斜杠,这在Linux上造成了问题。immeemosol的工作溶液见这里
Namespace Autoload works under windows, but not on Linux
命名空间Autoload在windows下工作,但在Linux上不工作
#8
1
Using has a gotcha, while it is by far the fastest method, it also expects all of your filenames to be lowercase.
使用有一个陷阱,虽然它是目前最快的方法,它也期望所有的文件名都是小写的。
spl_autoload_extensions(".php");
spl_autoload_register();
For example:
例如:
A file containing the class SomeSuperClass would need to be named somesuperclass.php, this is a gotcha when using a case sensitive filesystem like Linux, if your file is named SomeSuperClass.php but not a problem under Windows.
需要将包含SomeSuperClass的文件命名为SomeSuperClass。php,如果您的文件被命名为SomeSuperClass,那么在使用像Linux这样的区分大小写的文件系统时就会遇到这个问题。php,但在Windows下不是问题。
Using __autoload in your code may still work with current versions of PHP but expect this feature to become deprecated and finally removed in the future.
在代码中使用__autoload可能仍然适用于当前版本的PHP,但预期这个特性将被弃用,并最终在将来被删除。
So what options are left:
那么还有什么选择呢?
This version will work with PHP 5.3 and above and allows for filenames SomeSuperClass.php and somesuperclass.php. If your using 5.3.2 and above, this autoloader will work even faster.
这个版本将使用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;
});
#9
1
I recently found tanerkuc's answer very helpful! Just wanted to add that using strrpos()
+ substr()
is slightly faster than explode()
+ end()
:
我最近发现tanerkuc的答案非常有用!只是想补充一点,使用strrpos() + substr()要比explosion () + end()稍快一些:
spl_autoload_register( function( $class ) {
$pos = strrpos( $class, '\\' );
include ( $pos === false ? $class : substr( $class, $pos + 1 ) ).'.php';
});
#10
1
I'll throw in my two cents for relative beginners or whatnot wanting a simple spl_autoload_register() setup without all the theory: Just create one php file for each class, name that php file the same as your class name, and keep your class files in the same directory as your php file in question, then this will work:
我会把我的两个美分相对初学者或诸如此类的想要一个简单的spl_autoload_register()设置没有所有的理论:为每个类创建一个php文件,名字php文件与你的类名,并保持你的类文件在您的php文件相同的目录中,那么这将工作:
spl_autoload_register(function ($class_name) {
require_once dirname(__FILE__) . DIRECTORY_SEPARATOR . $class_name . '.php';
});
Googling the pieces inside this function should answer how it works. PS: I use Linux, and this works on Linux. Windows folks should test it out first.
用谷歌搜索这个函数的各个部分,就能知道它是如何工作的。PS:我用的是Linux,这在Linux上也适用。Windows用户应该首先测试它。
#11
1
https://thomashunter.name/blog/simple-php-namespace-friendly-autoloader-class/
https://thomashunter.name/blog/simple-php-namespace-friendly-autoloader-class/
You’ll want to put your class files into a folder named Classes, which is in the same directory as the entry point into your PHP application. If classes use namespaces, the namespaces will be converted into the directory structure. Unlike a lot of other auto-loaders, underscores will not be converted into directory structures (it’s tricky to do PHP < 5.3 pseudo namespaces along with PHP >= 5.3 real namespaces).
您将希望将类文件放入名为Classes的文件夹中,该文件夹与PHP应用程序的入口点位于同一个目录中。如果类使用名称空间,名称空间将被转换为目录结构。与许多其他自动加载程序不同,下划线不会被转换成目录结构(PHP < 5.3 pseudo namespaces with PHP >= 5.3 real namespace)。
<?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');
You’ll want to place the following code into your main PHP script (entry point):
您将希望将以下代码放入主PHP脚本(入口点):
require_once("Classes/Autoloader.php");
Here’s an example directory layout:
下面是一个目录布局示例:
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 {}
#12
0
<?php
spl_autoload_register(function ($classname){
// for security purpose
//your class name should match the name of your class "file.php"
$classname = str_replace("..", "", $classname);
require_once __DIR__.DIRECTORY_SEPARATOR.("classes/$classname.class.php");
});
try {
$new = new Class1();
} catch (Exception $e) {
echo "error = ". $e->getMessage();
}
?>
#1
104
Class1 is not in the global scope.
Class1不在全局范围内。
See below for a working example:
请参阅下面的工作示例:
<?php
function __autoload($class)
{
$parts = explode('\\', $class);
require end($parts) . '.php';
}
use Person\Barnes\David as MyPerson;
$class = new MyPerson\Class1();
Edit (2009-12-14):
编辑(2009-12-14):
Just to clarify, my usage of "use ... as" was to simplify the example.
只是为了澄清一下,我使用的“use…”as是为了简化例子。
The alternative was the following:
另一种选择是:
$class = new Person\Barnes\David\Class1();
or
或
use Person\Barnes\David\Class1;
// ...
$class = new Class1();
#2
22
As mentioned Pascal MARTIN, you should replace the '\' with DIRECTORY_SEPARATOR for example:
正如前面提到的Pascal MARTIN,您应该用DIRECTORY_SEPARATOR代替'\',例如:
$filename = BASE_PATH . DIRECTORY_SEPARATOR . str_replace('\\', DIRECTORY_SEPARATOR, $class) . '.php';
include($filename);
Also I would suggest you to reorganize the dirrectory structure, to make the code more readable. This could be an alternative:
我还建议您重新组织脏结构,使代码更可读。这可以是一个备选办法:
Directory structure:
目录结构:
ProjectRoot
|- lib
File: /ProjectRoot/lib/Person/Barnes/David/Class1.php
文件:/ ProjectRoot / lib /人/巴恩斯/大卫/ Class1.php
<?php
namespace Person\Barnes\David
class Class1
{
public function __construct()
{
echo __CLASS__;
}
}
?>
- Make the sub directory for each namespace you are defined.
- 为定义的每个名称空间创建子目录。
File: /ProjectRoot/test.php
文件:/ 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();
- I used php 5 recomendation for autoloader declaration. If you are still with PHP 4, replace it with the old syntax: function __autoload($class)
- 我使用php 5的recomendation来声明自动加载程序。如果您还在使用PHP 4,请使用旧语法替换它:function __autoload($class)
#3
15
Your __autoload
function will receive the full class-name, including the namespace name.
__autoload函数将接收完整的类名,包括名称空间名。
This means, in your case, the __autoload
function will receive 'Person\Barnes\David\Class1
', and not only 'Class1
'.
这意味着,在您的例子中,__autoload函数将接收“Person\Barnes\David\Class1”,而不仅仅是“Class1”。
So, you have to modify your autoloading code, to deal with that kind of "more-complicated" name ; a solution often used is to organize your files using one level of directory per "level" of namespaces, and, when autoloading, replace '\
' in the namespace name by DIRECTORY_SEPARATOR
.
因此,你必须修改你的自动读码,以处理那种“更复杂”的名字;通常使用的解决方案是使用每个名称空间“级别”的一个目录来组织文件,并且,当自动读取时,用DIRECTORY_SEPARATOR替换名称中的“\”。
#4
10
I do something like this:
我这样做:
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___
}
#5
3
I found this gem from Flysystem
我从Flysystem找到了这个宝石
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);
}
});
#6
3
I see that the autoload functions only receive the "full" classname - with all the namespaces preceeding it - in the following two cases:
我发现,autoload函数只接收“完整”类名——所有名称空间都在前面——在以下两种情况下:
[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();
I see that the autoload functions DO NOT receive the full classname in the following case:
我看到autoload函数在以下情况下不接收完整的类名:
[c] use The\Full\Namespace; (at the top of your source file) followed by $a = new CoolClass();
UPDATE: [c] is a mistake and isn't how namespaces work anyway. I can report that, instead of [c], the following two cases also work well:
更新:[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();
Hope this helps.
希望这个有帮助。
#7
1
had the same issue and just found this :
有同样的问题,刚刚发现:
When you create a subfolder structure matching the namespaces of the containing classes, you will never even have to define an autoloader.
当您创建与包含类的名称空间匹配的子文件夹结构时,您甚至不需要定义一个autoloader。
spl_autoload_extensions(".php"); // comma-separated list
spl_autoload_register();
It worked like a charm
它很有魅力
More info here : http://www.php.net/manual/en/function.spl-autoload-register.php#92514
更多信息:http://www.php.net/manual/en/function.spl-autoload-register.php#92514。
EDIT: this causes problem on Linux because of backslash... See here for working solution by immeëmosol
编辑:由于反斜杠,这在Linux上造成了问题。immeemosol的工作溶液见这里
Namespace Autoload works under windows, but not on Linux
命名空间Autoload在windows下工作,但在Linux上不工作
#8
1
Using has a gotcha, while it is by far the fastest method, it also expects all of your filenames to be lowercase.
使用有一个陷阱,虽然它是目前最快的方法,它也期望所有的文件名都是小写的。
spl_autoload_extensions(".php");
spl_autoload_register();
For example:
例如:
A file containing the class SomeSuperClass would need to be named somesuperclass.php, this is a gotcha when using a case sensitive filesystem like Linux, if your file is named SomeSuperClass.php but not a problem under Windows.
需要将包含SomeSuperClass的文件命名为SomeSuperClass。php,如果您的文件被命名为SomeSuperClass,那么在使用像Linux这样的区分大小写的文件系统时就会遇到这个问题。php,但在Windows下不是问题。
Using __autoload in your code may still work with current versions of PHP but expect this feature to become deprecated and finally removed in the future.
在代码中使用__autoload可能仍然适用于当前版本的PHP,但预期这个特性将被弃用,并最终在将来被删除。
So what options are left:
那么还有什么选择呢?
This version will work with PHP 5.3 and above and allows for filenames SomeSuperClass.php and somesuperclass.php. If your using 5.3.2 and above, this autoloader will work even faster.
这个版本将使用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;
});
#9
1
I recently found tanerkuc's answer very helpful! Just wanted to add that using strrpos()
+ substr()
is slightly faster than explode()
+ end()
:
我最近发现tanerkuc的答案非常有用!只是想补充一点,使用strrpos() + substr()要比explosion () + end()稍快一些:
spl_autoload_register( function( $class ) {
$pos = strrpos( $class, '\\' );
include ( $pos === false ? $class : substr( $class, $pos + 1 ) ).'.php';
});
#10
1
I'll throw in my two cents for relative beginners or whatnot wanting a simple spl_autoload_register() setup without all the theory: Just create one php file for each class, name that php file the same as your class name, and keep your class files in the same directory as your php file in question, then this will work:
我会把我的两个美分相对初学者或诸如此类的想要一个简单的spl_autoload_register()设置没有所有的理论:为每个类创建一个php文件,名字php文件与你的类名,并保持你的类文件在您的php文件相同的目录中,那么这将工作:
spl_autoload_register(function ($class_name) {
require_once dirname(__FILE__) . DIRECTORY_SEPARATOR . $class_name . '.php';
});
Googling the pieces inside this function should answer how it works. PS: I use Linux, and this works on Linux. Windows folks should test it out first.
用谷歌搜索这个函数的各个部分,就能知道它是如何工作的。PS:我用的是Linux,这在Linux上也适用。Windows用户应该首先测试它。
#11
1
https://thomashunter.name/blog/simple-php-namespace-friendly-autoloader-class/
https://thomashunter.name/blog/simple-php-namespace-friendly-autoloader-class/
You’ll want to put your class files into a folder named Classes, which is in the same directory as the entry point into your PHP application. If classes use namespaces, the namespaces will be converted into the directory structure. Unlike a lot of other auto-loaders, underscores will not be converted into directory structures (it’s tricky to do PHP < 5.3 pseudo namespaces along with PHP >= 5.3 real namespaces).
您将希望将类文件放入名为Classes的文件夹中,该文件夹与PHP应用程序的入口点位于同一个目录中。如果类使用名称空间,名称空间将被转换为目录结构。与许多其他自动加载程序不同,下划线不会被转换成目录结构(PHP < 5.3 pseudo namespaces with PHP >= 5.3 real namespace)。
<?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');
You’ll want to place the following code into your main PHP script (entry point):
您将希望将以下代码放入主PHP脚本(入口点):
require_once("Classes/Autoloader.php");
Here’s an example directory layout:
下面是一个目录布局示例:
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 {}
#12
0
<?php
spl_autoload_register(function ($classname){
// for security purpose
//your class name should match the name of your class "file.php"
$classname = str_replace("..", "", $classname);
require_once __DIR__.DIRECTORY_SEPARATOR.("classes/$classname.class.php");
});
try {
$new = new Class1();
} catch (Exception $e) {
echo "error = ". $e->getMessage();
}
?>