I'm playing around with the SPL autoload functionality and seem to be missing something important as I am currently unable to get it to work. Here is the snippet I am currently using:
// ROOT_DIRECTORY translates to /home/someuser/public_html/subdomains/test
define('ROOT_DIRECTORY', realpath(dirname(__FILE__)));
define('INCLUDE_DIRECTORY', ROOT_DIRECTORY . '/includes/classes/');
set_include_path(get_include_path() . PATH_SEPARATOR . INCLUDE_DIRECTORY);
spl_autoload_extensions('.class.php, .interface.php, .abstract.php');
spl_autoload_register();
When I echo get_include_path() I do get the path I expected:
// Output echo get_include_path();
.:/usr/lib/php:/usr/local/lib/php:/home/someuser/public_html/subdomains/test/includes/classes/
However when I run the code I get this error message:
Fatal error: spl_autoload() [function.spl-autoload]: Class Request could not be loaded in
/home/someuser/public_html/subdomains/test/contact.php
on line 5
Request.class.php is definitely in the /home/someuser/public_html/subdomains/test/includes/classes/ directory.
What am I missing?
There is a comment (anonymous) on http://www.php.net/manual/en/function.spl-autoload-register.php#96804 that may apply to your problem: spl_autoload_register() doesn't seem to play nice with camelcase, and in your case could be trying to find request.class.php instead of Request...
The path where the class is supposed to be seems not to match the path were you expect them. Compare
.:/usr/lib/php:/usr/local/lib/php:/home/someuser/public_html/subdomains/test/includes/classes/
with
/home/someuser/public_html/subdomains/test/
The difference is, that your class is not in includes/classes/ as your SPL requires it but a few directories above.
I got a similar error message but my issue was different. My error message looked like
PHP Fatal error: spl_autoload(): Class Lib\Lib\Regex could not be loaded in /dir1/dir2/lib/regex.php on line 49
It turned out I forgot to remove the Lib\ from Lib\Regex inside the Regex class definition itself. I had something like the following:
namespace Lib;
class Regex {
...
public static function match($pattern, $str) {
$regex = new Lib\Regex($pattern);
...
}
}
Related
I am just getting my feet wet with PHP autoloading. I actually think I got the basics down, but somehow it still won't work.
I got the following directory structure:
myLib
-bootstrap.php
-sven
-project
project.php
bootstrap.php is the file that will be included to use the lib. In this file, I simply have the following code:
spl_autoload_extensions('.php');
spl_autoload_register();
$var = new \sven\project\project();
$var->init();
And in project.php:
namespace sven\project;
class project {
public function init() {
echo 'It works!';
}
}
The way the autoloader is used, to my understanding, the core PHP autoloader should translate the namespace into directories and then look for a php containing the class.
Instead of displaying 'It works!', a fatal error is thrown. Unfortunately, I can't exactly tell what that error is because the CMS only informs me that there was a fatal error.
But with such a simple structure, I am sure the error is pretty basic and easy to find for someone who knows how it works.
Where am I going wrong with this example – did I correctly describe how the autoloader should work in this setup or is there a misunderstanding?
EDIT: Finally got the error log running:
Fatal error: Class undefined: sven\\project\\project\\project\\project in /xxx/bootstrap.php on line 36
That obviously looks wrong, but how to change that? Why are there two backslashes?
spl_autoload_extensions('.php');
spl_autoload_register();
This code works only with PHP 5.3 and above.
Sven,
I just answered another question about spl_autoload, try my example click here
I hope it helps!
PS:
Also don't just autoload all .php files on your path , that can be dangerous !
How smart is spl_autoload_register? Does it know to "look ahead" for the class definition in other files before trying to include?
When I run my index.php page I'm seeing
Fatal error: Class 'input\input' not found in /var/www/php/classes/input/date.php on line 4
index.php runs the following (after this block it creates an object from one of the classes, if I uncomment the one line everything works perfectly)
function my_autoloader() {
//include_once "/var/www/php/classes/input/input.php"; //if this is uncommented, it fixes the problem, but I'm not sure why
foreach (glob("/var/www/php/classes/*/*.php") as $filename)
{
require_once $filename;
}
}
spl_autoload_register('my_autoloader');
is my syntax wrong? is spl_autoload_register supposed to function this way? many other files in these folders depend on eachother and the autoloader seems to "figure it out". I'm not sure why it is suddenly hung up on the "input" class in particular
You're using the autoloader in a wrong way. It is only supposed to load the classes you need for a specific request, not the whole folder.
Read more about autoloading classes properly with some good examples: https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-0.md
You are using it wrongly.
The autoload is used for autoloading only the given class name on the 1st argument of callback, not for loading all classes like you're doing.
For example:
spl_autoload_register(function ($class) {
// ...
$class = stream_resolve_include_path(sprintf("%s.php", $class));
if ($class !== false) {
require $class
}
});
$class will contains the class to load it, so, you can use it to find the file containing this class at your filesystem.
This is a WordPress local installation that I am trying to work with. I have not written a single line of this code myself. I don't understand what this error means:
Fatal error: Cannot redeclare class Config in /Applications/XAMPP/xamppfiles/lib/php/Config.php on line 44
Line 44 reads as follows:
class Config {
My guess is that a Config class has either already been declared elsewhere, or that this file is being executed for the second time.
That usually happens when you declare a class more than once in a page -- maybe via multiple includes.
To avoid this, use require_once instead. If you use require_once PHP will check if the file has already been included, and if so, not include (require) it again.
Say, for example, you have the following code:
<?php
class foo {
# code
}
... more code ...
class foo { // trying to re-declare
#code
}
In this case, PHP will throw a fatal error similar to the one below:
Fatal error: Cannot redeclare class foo in /path/to/script.php on line 7
In this case it's very simple -- simply find the 7th line of your code and remove the class declaration from there.
Alternativey, to make sure you don't try to re-declare classes, you can use the handy class_exists() function:
if(!class_exists('foo')) {
class foo {
# code
}
}
The best approach, of course, would be to organize all the configurations in one single file called config.php and then require_once it everywhere. That way, you can be sure that it will be included only once.
As for debugging the error, you could use debug_print_backtrace().
It's possible that the theme you are using refers to a file called config.php. If so use the following steps.
Try to find the config.php file and change it's name to configuration.php.
Find the files where they use config.php in the code and change it to configuration.php.
I am trying to load a class in order for a PHP script that I wrote, with help of the classes' documentation, to work.
Since my server is running PHP 5.3, the documentation recommended loading the class like this:
spl_autoload_register(function($class){
if (file_exists('/webgit/webroot/home/myUsername/www/elastica/lib/' . $class . '.php')) {
echo " found \n ";
require_once('/webgit/webroot/home/myUsername/www/elastica/lib/' . $class . '.php');
}
else {
echo " not found! ";
}
});
The only things that are different are that I included echo's in the suite of the if and else.
Also myUsername is actually my username in the file-system path on the server.
Then, it ( the documentation ) suggests that I make a new instance of the class like so:
$elasticaClient = new \Elastica\Client();
However, I am getting an error that the class is not found. Here is exactly what is printed including the error and the suite of my if-else:
not found! Fatal error: Class 'Elastica\Client' not found in /webgit/webroot/home/myUsername/www/elastica/index.php on line 17
line 17 is the line where I try to make an instance of the class.
now, index.php is where the above code is and it is located, on my server, in /webgit/webroot/home/myUsername/www/elastica/
and all the class files are in /webgit/webroot/home/myUsername/www/elastica/lib/
so, I don't understand why it is not able to find / load the class.
I would greatly appreciate any help in solving this!
not found! - it's mean that the file was not found. File, not class.
Variable $class contains full class name with namespaces Elastica\Client. Are you sure that you have /webgit/webroot/home/myUsername/www/elastica/lib/Elastica\Client.php file?
Check How do I use PHP namespaces with autoload? and learn about PSR-0.
Redacted due to excessive wrongness. Mike has a link in the comments worth preserving, however.
I have had some really strange errors here with php today.
I've written a little class for A/B Testing and wanted to create a new instance in a php document of mine:
if(!class_exists('ab_tester')) include('../lib/php/ab_tester.php');
$ab = new ab_tester($user['id']);
One would think this should do the trick, but php says:
Fatal error: Cannot redeclare class ab_tester in [PATH_TO_PHP]ab_tester.php on line 10
Why does this happen?
Note: Line 10 of the ab_tester.php looks like this:
class ab_tester {
If I leave the include line out, creating a new instance of ab_tester, it spits out:
Fatal error: Class 'ab_tester' not found in [PATH_TO_PHP]returning.php on line 25
What do I do now? If I try to import it, it's already there and if I don't, its missing.
And what do the first 9 lines of code in ab_tester.php contain?
I bet that there is another class ab_tester there (or in an include, anyway)
EDIT:
Another possible explanation is that you are doing a second include of ab_tester.php later on the code of returning.php. So even if you use include_once in this particular line, the second call is still just an include...
How about:
include_once('../lib/php/ab_tester.php');
$ab = new ab_tester($user['id']);
?
Try autoloading classes instead of using includes?
function __autoload($class_name){
$class_name = strtolower($class_name);
$path = "../includes/{$class_name}.php";
if(file_exists($path)){
require_once($path);
}else{
die("The file {$class_name}.php could not be found.");
}
}