简体   繁体   中英

How to use roots classes in all namespaces automatically with spl_autoload?

It is possible to make accessible a Class within spl_autoload_register (automatically)?

For example, I using spl_autoload_register in index.php:

<?php
class Utils {
   public function example() {
      echo 'Hello word!';
   }
}

spl_autoload_register(function($class)
{
    $relative_class = strtolower(str_replace('\\', '/', $class));

    $file = './src/' . $relative_class . '.php';

    if (is_file($file)) {
        require_once $file;
    }
});

$user = new \Controllers\Foo\User;

This new \\Controllers\\Foo\\User; autoload this file ./src/controllers/foo/user.php

user.php:

<?php
namespace Controllers/Foo;

class User
{
    public function foo() {
        //Something...
    }
}

If I need to use a Utils class I'll have to add new \\Controllers\\Foo\\User in the file user.php like this:

public function foo() {
   \Utils::example();
}

or

<?php
namespace Controllers/Foo;

use \Utils as Utils;

class User
{
    public function foo() {
        Utils::example();
    }
}

It is possible to make accessible to Utils class within spl_autoload_register (automatically)? I would use without use \\Utils as Utils; and without backslash ( \\Utils:: ).

You can't. That's the whole point of using namespaces. You can reference a class whitout backslash or use statement only if it is in the same namespace you are using it. You can't hack the autoloader to automagically import the target class into the current namespace changing its namespace on the fly.

If your class doesn't belong to a named namespace, then it is in the global namespace and you still have to use with \\ or use . The same for import or use keywords in python, java, go, .net, c/c++, etc.

There is no standard anything to do this besides using use ... as ... or "backslash" ( \\ ), however we can "cheat the PHP" using eval() within the spl_autoload_register() to extend the Utils class within the namespace .

Only use this if really necessary, prefer to use "backslash" ( \\ ) or use \\Utils as Utils

Example (read comments in code):

<?php
class Utils {
   public static function example() {
      echo 'Hello World!';
   }
}

spl_autoload_register(function($class)
{
    $relative_class = strtolower(str_replace('\\', '/', $class));

    $file = './src/' . $relative_class . '.php';

    if (is_file($file)) {
        $np = explode('\\', $class); //Dividi string

        //Check if class exists in namespace (prevent conflicts)
        if (class_exists(implode('::', $np)) === false) {

            //Remove "class name", use only "namespace"
            array_pop($np);

            //evaluate a namespace in eval (extends the Utils class)
            eval(
                'namespace ' . implode('\\', $np) . ' {' . PHP_EOL .
                'class Utils extends \Utils {}' . PHP_EOL .
                '}'
            );
        }

        require_once $file;
    }
});

$user = new \Controllers\Foo\User;
$user->foo(); //Show "Hello word!"

I admit that it is an ugly hack and maybe I will not use, but it's still a hint yes.

Note: use \\Utils as Utils not work in eval

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM