0

I am trying to understand how to define a working autoloader for a trivial application with namespaces.

I created following structure:

public
    index.php
src
    Models
        WordGenerator.php

Obviously, later it will grow. The WordGenerator.php file is following:

<?php
namespace Models;

class WordGenerator {
    public $filename;

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

Now I try to create instance of this object in index.php:

<?php
use \Models;

$wg = new WordGenerator("words.english");

Obviously I get fatal error because I did not define autoloader. However though, according to documentation all I can pass is $classname. How should I define the autoloader function to take namespace declared by use statement then??

[edit] I was wrong understood a moment ago. So here's my code for index.php:

spl_autoload_register(function ($className) {
    $className = ltrim($className, '\\');
    $prepend = "..\\src\\";
    $fileName  = "{$prepend}";
    $namespace = '';
    if ($lastNsPos = strrpos($className, '\\')) {
        $namespace = substr($className, 0, $lastNsPos);
        $className = substr($className, $lastNsPos + 1);
        $fileName  = $prepend.str_replace('\\', DIRECTORY_SEPARATOR, $namespace) . DIRECTORY_SEPARATOR;
    }
    $fileName .= str_replace('_', DIRECTORY_SEPARATOR, $className) . '.php';

    require $fileName;
});
//require '../src/Models/WordGenerator.php';

use Models;

$wg = new WordGenerator("words.english");
echo $wg->getRandomWord();

Now, this does not work and I get:

Warning: The use statement with non-compound name 'Models' has no effect in C:\xampp\htdocs\Hangman\public\index.php on line 22

Warning: require(..\src\WordGenerator.php): failed to open stream: No such file or directory in C:\xampp\htdocs\Hangman\public\index.php on line 16

Fatal error: require(): Failed opening required '..\src\WordGenerator.php' (include_path='.;C:\xampp\php\PEAR') in C:\xampp\htdocs\Hangman\public\index.php on line 16

However when I change new WordGenerator to new \Models\WordGenerator it works. Now, the question is: how can I pass namespaces declared by use statement to autoloader function to make it work properly?

0

2 Answers 2

2

Your use statement is incorrect. You want use Models\WordGenerator;

The use operator doesn't declare anything but an alias. Consider the expanded form:

use Models\WordGenerator as WordGenerator;

Which is equivalent.


You can alias a namespace rather than a class, but it doesn't work in the way you're attempting. For example:

use Models as Foo;
$wg = new Foo\WordGenerator("words.english");

Would work. However:

use Models;

Is equivalent to:

use Models as Models;

Which effectively does nothing.


For more information see Using namespaces: Aliasing/Importing in the PHP manual.

Sign up to request clarification or add additional context in comments.

1 Comment

Cannot I use whole namespace as in C++?
0

Please look at documentation. Autoloader must be defined by you at beginning of you script. At provided link there is example autoloader and more complex solution

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.