How to use PHP namespaces with autoload?

I get this error when I try to use autoload and namespaces:

Fatal error: Class 'Class1' could not be found in /usr/local/www/apache22/data/public/php5.3/test.php on line 10

Can someone tell me what I am doing wrong?

Here is my code:

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(); ?> 
+78
php autoload
Dec 02 '09 at 5:55
source share
11 answers

Class 1 is not in the global scope.

The following is 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):

To clarify, my use of "use ... as" was to simplify the example.

An alternative was the following:

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

or

 use Person\Barnes\David\Class1; // ... $class = new Class1(); 
+92
Dec 09 '09 at 1:35
source share

As Pascal MARTIN mentioned, you should replace '\' with DIRECTORY_SEPARATOR, for example:

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

In addition, I would suggest you rebuild 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

 <?php namespace Person\Barnes\David class Class1 { public function __construct() { echo __CLASS__; } } ?> 
  • Create a subdirectory for each namespace that you define.

File: /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 recommendation to declare autoloader. If you are still using PHP 4, replace it with the old syntax: function __autoload ($ class)
+22
May 14 '13 at 1:01
source share

Your __autoload function will get the fully qualified class name, including the namespace name.

This means that in your case, the __autoload function will get " Person\Barnes\David\Class1 ", not just " Class1 ".

So, you need to change your startup code to deal with such a “more complex" name; A frequently used solution is to organize your files using one directory level on the "level" of namespaces and at startup, replace " \ " with the namespace name on DIRECTORY_SEPARATOR .

+14
Dec 02 '09 at 6:00
source share

I am doing 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___ } 
+10
May 31 '15 at 18:05
source share

I see that startup functions get only the "full" class name - with all spaces preceding them - in the following two cases:

 [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 autoload functions DO NOT get the full class name in the following case:

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

UPDATE: [c] is an error, not the way namespaces work anyway. I can report that instead of [c] the following two cases also work:

 [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.

+3
Aug 21 '13 at 16:07 on
source share

I found this stone from 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); } }); 
+3
Feb 15 '15 at 20:20
source share

had the same problem and just found this:

When you create a subfolder structure that matches the namespaces of the contained classes, you don’t even have to define an autoloader.

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

He worked like a charm

Further information here: http://www.php.net/manual/en/function.spl-autoload-register.php#92514

EDIT: this causes a problem on Linux due to the backslash ... See here for a working immeëmosol solution

Autoload namespace works under windows, but not on Linux

+1
Jul 03 '14 at 13:23
source share

Usage has gotcha, although this is by far the fastest method, it also expects all of your file names to be lowercase.

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

For example:

The file containing the SomeSuperClass class should be named somesuperclass.php, this will be obtained using a case-sensitive file system such as Linux, if your file is called SomeSuperClass.php, but not a problem on Windows.

Using __autoload in your code may still work with current versions of PHP, but expect this feature to become obsolete and finally removed in the future.

So what options are left:

This version will work with PHP 5.3 and higher and allows the file names SomeSuperClass.php and somesuperclass.php. If you use 5.3.2 and higher, this autoloader will run even faster.

 <?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; }); 
+1
Apr 08 '15 at 1:28
source share

I will throw my two cents for relative beginners or I don’t want to simply set spl_autoload_register () without any theory: Just create one php file for each class, name this php file the same as your class name, and save the class files in the same directory. as your php file, then this will work:

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

The inclusion of a function in this function should be consistent with how it works. PS: I use Linux and it works on Linux. Windows people should check this out first.

+1
Aug 22 '16 at 5:45
source share

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

You want to put your class files in a folder called Classes, which is located in the same directory as the entry point to your PHP application. If classes use namespaces, namespaces will be converted to a directory structure. Unlike many other autoloaders, underscores will not be converted to directory structures (it is difficult to use PHP pseudo-spaces and lt instead of 5.3, as well as real PHP namespaces> = 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'); 

You want to put the following code in your main PHP script (entry point):

 require_once("Classes/Autoloader.php"); 

Here is 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 {} 
+1
Oct 26 '17 at 7:33
source share

I recently found tanerkuc's answer very helpful! Just wanted to add that using strrpos() + substr() little faster than explode() + end() :

 spl_autoload_register( function( $class ) { $pos = strrpos( $class, '\\' ); include ( $pos === false ? $class : substr( $class, $pos + 1 ) ).'.php'; }); 
0
Aug 05 '16 at 2:18
source share



All Articles