0
votes

I don't know if I'm missing something but using namespaces seems to break my application. It won't find the parent class because it includes the namespace in the class name when the autoload register gets called

spl_autoload_register(function($classname){
    if (preg_match('/[a-zA-Z]+Controller$/', $classname)) {
        echo __DIR__ . '/controllers/' . $classname.".php" . "<br />";
        require __DIR__ . '/controllers/' . $classname.".php";
    }
});

//echo produces:
/var/www/web/controllers/DefaultController.php
/var/www/web/controllers/Project\Controllers\BaseController.php

Project\Controllers is the namespace used in both default and base controller. Default extends base controller.

Why is spl autoload doing this?

Structure:

web/controllers:

BaseController.php

DefaultController.php

BaseController:

namespace Project\Controllers;

class BaseController
{
    private $config;

    public function __construct($config)
    {
        $this->config = $config;
    }
}

DefaultController:

<?php
namespace Project\Controllers;

class DefaultController extends BaseController
{
}
1
@MichaelBerkowski I'm so confused. The namespace is declared in both files. How would you include a file when taking the namespace into account? - iswinky

1 Answers

0
votes

The main problems seems to be that your autoloader is not aware of the root namespace which it belongs to. So really your autoloader should be made aware of or be part of the namespace so in this case Project.

So the first thing your autoload needs to do is remove the known root namespace (unless of course it is used as part of the file structure which in this case it isn't)

<?php namespace Project;

// Within the namespace
$classname = ltrim(str_replace(__NAMESPACE__ . '\\', '', $classname), '\\');

// Outside of the namespace
$classname = ltrim(str_replace('Project\\', '', $classname), '\\');

Now for the class name and the actual file location.

// find the last backslash
if($last = strripos($classname, '\\')) {
    $namespace = substr($classname, 0, $last); // Controllers
    $classname = substr($classname, $last+1); // DefaultController
}

Now you can built the actual file location to the PHP class file

$filepath = '/var/www/'; // Root
if(isset($namespace)) {
    // Add the controllers bit onto the root
    $filepath .= str_replace('\\', DIRECTORY_SEPARATOR, $namespace) . DIRECTORY_SEPARATOR;
}
// add the class name (DefaultController) to the file path
$filepath .= str_replace('\\', DIRECTORY_SEPARATOR, $classname) . '.php';

This should result in with the following filepaths which can be checked if exists then included if they do.

/var/www/Controllers/BaseController.php

/var/www/Controllers/DefaultController.php