1
votes

I am getting an error when trying to use an autoloader for dynamic loading of the classes I need to use. I've tried a few things, but it fails.

I guess it must be some very silly error in setting up directories, but I have already tried to remove or insert relative paths, "Use"'s, etc.

How can I proceed?

Error on /admin/index.php

Fatal error: Uncaught Error: Class 'Connection' not found in /Applications/XAMPP/xamppfiles/htdocs/common/Class/Database/Sql.php:11 Stack trace: #0 /Applications/XAMPP/xamppfiles/htdocs/common/autoload.php(22): require_once() #1 [internal function]: {closure}('Database/Sql') #2 /Applications/XAMPP/xamppfiles/htdocs/common/Class/App/Specialty.php(11): spl_autoload_call('Database\Sql') #3 /Applications/XAMPP/xamppfiles/htdocs/common/autoload.php(22): require_once('/Applications/X...') #4 [internal function]: {closure}('App/Specialty') #5 /Applications/XAMPP/xamppfiles/htdocs/admin/index.php(11): spl_autoload_call('App\Specialty') #6 /Applications/XAMPP/xamppfiles/htdocs/index.php(21): include('/Applications/X...') #7 {main} thrown in /Applications/XAMPP/xamppfiles/htdocs/common/Class/Database/Sql.php on line 11

Dir Structure

- /Common
   - /Class
      - /Database
         - Connection.php
         - Query.php
         - Sql.php
      - /App
         - Specialty.php
      - autoload.php
 - /admin
   - index.php

And the files...

/admin/index.php

$objTeste = new App\Specialty();
$objTeste->save();

/common/autoload.php

spl_autoload_register(function($className){

    $ds = DIRECTORY_SEPARATOR;
    $dir = __DIR__."/Class";

    $className = str_replace('\\', $ds, $className);

    $file = "{$dir}{$ds}{$className}.php";

    if (is_readable($file)) require_once $file;

});

/common/Class/App/Specialty.php

class Specialty extends Database\Sql
{
    use Database\Query;
    ...
}

/common/Class/Database/Sql.php

class Sql extends Connection
{
    ...
}

/common/Class/Database/Query.php

trait Query
{
    ...
}

/common/Class/Database/Sql.php

class Sql extends Connection
{
    ...
}

/common/Class/Database/Connection.php class Connection { ... }

An important detail: I print_r() inside the autoloader to find out if the class path was being generated correctly, and guess what... it was!

print_r($file);
# /Applications/XAMPP/xamppfiles/htdocs/Common/Class/Database/Connection.php

Test if the $file is readable

if(is_readable($file)){
    print_r($file." found<br>");
}
else{
    print_r($file." not found<br>");
}

# Result: /Applications/XAMPP/xamppfiles/htdocs/Common/Class/Database/Connection.php found
1
@Jeto sorry, you're right. I cut off a piece of the result for considering it irrelevant. But the correct result contemplates the absolute path. I've edited the question right now!Maykel Esser
@Jeto i tried to use with upper/lowercase. Now, all the references are using the uppercase Class name. And the same error persists.Maykel Esser
@Jeto nvm, i just copy/paste a old print_r. But there was a uppercase Class. I tried to get if $path is_readable... i'll edit the question with the result.Maykel Esser
Since you're referencing Database\Sql and stuff like this, PHP is interpreting them (the parts before the last one) as namespaces. Are you using any namespace declarations on top of your files?Jeto
Should be whatever comes after Class/ in your folder structure. E.g. Connection should be in the Database namespace, Specialty in the App namespace, etc.Jeto

1 Answers

1
votes

Since you're using backslashes in your class names, PHP interprets everything that comes before the last one as a namespace.

For instance, when you're doing this:

class Specialty extends Database\Sql

PHP reads this as "define a class Specialty that extends a class Sql present in the Database namespace".

So to fix your issues (and make your code cleaner in the meantime), simply add the proper namespace declaration on top of your files, based on whatever comes after Class/ in your folder structure (since that's the root folder your autoloader is using).

e.g.:

namespace Database;

class Sql {
  ...
}