1

I've tried multiple PSR-4 loaders, but they either don't work or I can't access the classes from another folder.

My current folder structure:

-Classes

--Config.php

--Session.php

--Frontend (folder)

---Login.php

PSR-4 Autoloader:

I tried to load all classes using the PSR-4 autoload register. I modified it slightly to my folder structure. I've given all classes the namespace Classes, but the ones in the Frotend folder has the namespace Classes\Frontend.

spl_autoload_register(function ($class) {

    // project-specific namespace prefix
    $prefix = 'Classes\\';

    // base directory for the namespace prefix
    $base_dir = __DIR__ . '/Classes/';

    // does the class use the namespace prefix?
    $len = strlen($prefix);
    if (strncmp($prefix, $class, $len) !== 0) {
        // no, move to the next registered autoloader
        return;
    }

    // get the relative class name
    $relative_class = substr($class, $len);

    // replace the namespace prefix with the base directory, replace namespace
    // separators with directory separators in the relative class name, append
    // with .php
    $file = $base_dir . str_replace('\\', '/', $relative_class) . '.php';

    // if the file exists, require it
    if (file_exists($file)) {
        require $file;
    }
});

I'm not sure if this has to do with the autoloader, but I also want to call the class from any file wherever it's located. So if I have a file in

/Frontend/templates/login-page.php

I want to be able to call the class "Classes\Frontend\Login".

Is this possible and how would I do that?

Community
  • 1
  • 1
Stefan R
  • 404
  • 2
  • 8
  • 30
  • 1
    do you have [composer](https://getcomposer.org/)? – Wee Zel Sep 11 '17 at 18:43
  • 1
    Please, just use `composer`! – localheinz Sep 11 '17 at 20:10
  • I'm creating some sort of library which should be easy to implement in other projects. Using composer is not an option for that. I have been using composer for a stand-alone project, that's why I don't know how to do this properly without composer – Stefan R Sep 11 '17 at 20:40
  • 1
    If you are creating a library and do not use `composer`, you will be the only one using that library. – localheinz Sep 11 '17 at 21:04

1 Answers1

3

There are mainly two ways to get it working: The first option is to use an absolute server path (starting with a '/'), to set the base directory for your classes in your autoload function:

spl_autoload_register(function ($class) {

    $prefix = 'Classes\\';
    $base_dir = '/var/www/html/my_project/src/'; // your classes folder
    $len = strlen($prefix);
    if (strncmp($prefix, $class, $len) !== 0) {
        return;
    }
    $relative_class = substr($class, $len);
    $file = $base_dir . str_replace('\\', '/', $relative_class) . '.php';
    if (file_exists($file)) {
        require $file;
    }
});

The better solution is, as @Félix suggested, to stick with the __DIR__ constant to keep things relative to your project folder. Absolute paths are brittle between deployments on different servers. __DIR__ refers to the directory of the file it is used in; in this case it is where you register the autoload function. Starting from this directory, you can navigate to the classes base directory, for example $base_dir = __DIR__ . '/../../src/;

Don't forget to namespace your classes:

namespace Classes;

class Foo
{
    public function test()
    {
       echo 'Hurray';
    }
 }

Then use classes like this:

$foo = new Classes\Foo();
$foo->test();
Benni
  • 1,023
  • 11
  • 15
  • Ah, yeah. I completely forgot my file is located somewhere else. But I'm still not able to use my classes in a file which is located somewhere else. Right now the autoload is being done in the index.php (root of the project). I can approach the classes just fine in (for example) /etc/test.php. However, when I use the same classes in /Frontend/templates/pages/test.php, I get an error the class cannot be found and I have to require it manually. Is there any solution for this? – Stefan R Sep 11 '17 at 20:38
  • 1
    Are you sure you used an absolute path starting with a backslash? This should work independently from the calling script's folder. – Benni Sep 12 '17 at 06:10