How do I use PHP namespaces with autoload?
Solution 1
Class1
is not in the global scope.
Note that this is an old answer and things have changed since the days where you couldn't assume the support for spl_autoload_register()
which was introduced in PHP 5.1 (now many years ago!).
These days, you would likely be using Composer. Under the hood, this would be something along the lines of this snippet to enable class autoloading.
spl_autoload_register(function ($class) {
// Adapt this depending on your directory structure
$parts = explode('\\', $class);
include end($parts) . '.php';
});
For completeness, here is the old answer:
To load a class that is not defined in the global scope, you need to use an autoloader.
<?php
// Note that `__autoload()` is removed as of PHP 8 in favour of
// `spl_autoload_register()`, see above
function __autoload($class)
{
// Adapt this depending on your directory structure
$parts = explode('\\', $class);
require end($parts) . '.php';
}
use Person\Barnes\David as MyPerson;
$class = new MyPerson\Class1();
or without aliases:
use Person\Barnes\David\Class1;
$class = new Class1();
Solution 2
As mentioned Pascal MARTIN, you should replace the '\' with DIRECTORY_SEPARATOR for example:
$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
<?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
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)
Solution 3
Your __autoload
function will receive the full class-name, including the namespace name.
This means, in your case, the __autoload
function will receive 'Person\Barnes\David\Class1
', and not only '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
.
Solution 4
I do something like this: See this GitHub Example
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___
}
Solution 5
I see that the autoload functions only receive the "full" classname - with all the namespaces preceeding it - 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 the autoload functions DO NOT receive the full classname in the following case:
[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:
[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.
Related videos on Youtube
David Barnes
I work as a Software Engineer in Minneapolis, Minnesota.
Updated on July 08, 2022Comments
-
David Barnes almost 2 years
I get this error when I try to use autoload and namespaces:
Fatal error: Class 'Class1' not found in /usr/local/www/apache22/data/public/php5.3/test.php on line 10
Can anyone 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(); ?>
-
David Barnes over 14 yearsThis is not what I found. When I did put the statement die($class); in the __autoload function, it printed out 'Class1"', not 'Person\Barnes\David\Class1'
-
tishma about 11 yearsTrue. $class parameter of autoload is the class name as written in constructor call.
-
cartbeforehorse over 10 yearsYou don't have to use
AS
. That's not why this solution works. You could just as easily do:use Person\Barnes\David\Class1;
(which is equivalent touse Person\Barnes\David\Class1 as Class1;
). -
user345602 about 10 yearsThanks ,this works. But I cant understand why we can just use $class = new Class1(); when we have already defined "use Person\Barnes\David; " before ?
-
Justin C about 10 years@user346665 you must use
use Person\Barnes\David\Class1;
in order to do$class = new Class1();
. Withuse Person\Barnes\David;
you must do$class = new David\Class1();
. Theuse
keyword by itself is the equivalent ofuse Person\Barnes\David\Class1 as Class1;
oruse Person\Barnes\David as David;
, respectively for each example. -
Mark Amery over 9 yearsDownvote for "Your
__autoload
function will receive the full class-name, including the namespace name" - this is only true if you have explicitlyuse
d the class you're trying to reference, not if you've merelyuse
d the namespace it belongs to. The OP's mistake was that he'duse
d the namespace containing a class and was then expecting his autoload function to magically get passed the full classpath somehow. This answer doesn't really address the OP's mistake. -
Andrew Larsson about 9 yearsAs a side note, the
use
keyword doesn't work properly in the PHP interactive command-line interface (php --interactive
); -
dennis almost 9 yearsNice and simple. If one should be looking for that .)
-
Itay Moav -Malimovka about 8 yearsas a side note,
str_replace ([ '_','\\'] '/', $className );
is twice as fast than two str_replace -
Mike over 7 yearsAs long as it doesn't matter if the php file is upper/lower cased, the directories still remain case sensisive
-
Ethan almost 6 yearsWhile this code may answer the question, providing additional context regarding why and/or how this code answers the question improves its long-term value.
-
Bruno de Oliveira over 5 yearsFor those reading in 2018, use @prince-billy-graham solution with spl_autoload_register