Search code examples
phpnamespacesmustache.php

Mustache.php initiated from within a namespace - include(): failed to open stream


When using a simple autoloader, Mustache.php initiated from within a namespace webpage renders the data properly but also returns a long list of warnings about failures to include many of its files. Mustache is loaded by requiring its Autoloader.php, as recommended by its official documentation.

I have found several posts (1, 2) that discuss a similar issue. The typical solution is to prepend \ in front of Mustache_Autoloader::register(); to load it in the global namespace. However, that doesn't seem to work for me.

The same list of warnings is generated both on Google Cloud PHP Development Server (5.5.26) and the full-fledged PHP server (7.1.9).

The minimal code is below.

Directory structure:

.
│   index.php
└───app
    ├───controllers
    │   └───webpage
    │           home.php
    └───vendor
        └───Mustache
                Autoloader.php

Content of index.php:

function autoloader($class)
{
    include($_SERVER['DOCUMENT_ROOT'] . '/app/controllers/' . $class . '.php');
}
spl_autoload_register('autoloader');

new \webpage\home;

Content of home.php:

namespace webpage;

class home
{
    function __construct()
    {
        require $_SERVER['DOCUMENT_ROOT'] . '/app/vendor/Mustache/Autoloader.php';

        \Mustache_Autoloader::register();

        $mustache = new \Mustache_Engine();

        echo $mustache->render('Hello {{planet}}', array('planet' => 'World!'));
    }
}

Notice that at the very bottom of the output is a properly rendered string "Hello World".

Warning: include(D:/project/app/controllers/Mustache_Engine.php): failed to open stream: No such file or directory in D:\project\index.php on line 5

Warning: include(): Failed opening 'D:/project/app/controllers/Mustache_Engine.php' for inclusion (include_path='.;D:\project;C:\Program Files (x86)\Google\Cloud SDK\google-cloud-sdk\platform\google_appengine\php\sdk') in D:\project\index.php on line 5

Warning: include(D:/project/app/controllers/Mustache_Loader_StringLoader.php): failed to open stream: No such file or directory in D:\project\index.php on line 5

Warning: include(): Failed opening 'D:/project/app/controllers/Mustache_Loader_StringLoader.php' for inclusion (include_path='.;D:\project;C:\Program Files (x86)\Google\Cloud SDK\google-cloud-sdk\platform\google_appengine\php\sdk') in D:\project\index.php on line 5

Warning: include(D:/project/app/controllers/Mustache_Loader.php): failed to open stream: No such file or directory in D:\project\index.php on line 5

Warning: include(): Failed opening 'D:/project/app/controllers/Mustache_Loader.php' for inclusion (include_path='.;D:\project;C:\Program Files (x86)\Google\Cloud SDK\google-cloud-sdk\platform\google_appengine\php\sdk') in D:\project\index.php on line 5

Warning: include(D:/project/app/controllers/Mustache_Cache_NoopCache.php): failed to open stream: No such file or directory in D:\project\index.php on line 5

Warning: include(): Failed opening 'D:/project/app/controllers/Mustache_Cache_NoopCache.php' for inclusion (include_path='.;D:\project;C:\Program Files (x86)\Google\Cloud SDK\google-cloud-sdk\platform\google_appengine\php\sdk') in D:\project\index.php on line 5

Warning: include(D:/project/app/controllers/Mustache_Cache_AbstractCache.php): failed to open stream: No such file or directory in D:\project\index.php on line 5

Warning: include(): Failed opening 'D:/project/app/controllers/Mustache_Cache_AbstractCache.php' for inclusion (include_path='.;D:\project;C:\Program Files (x86)\Google\Cloud SDK\google-cloud-sdk\platform\google_appengine\php\sdk') in D:\project\index.php on line 5

Warning: include(D:/project/app/controllers/Mustache_Cache.php): failed to open stream: No such file or directory in D:\project\index.php on line 5

Warning: include(): Failed opening 'D:/project/app/controllers/Mustache_Cache.php' for inclusion (include_path='.;D:\project;C:\Program Files (x86)\Google\Cloud SDK\google-cloud-sdk\platform\google_appengine\php\sdk') in D:\project\index.php on line 5

Warning: include(D:/project/app/controllers/Mustache_Logger.php): failed to open stream: No such file or directory in D:\project\index.php on line 5

Warning: include(): Failed opening 'D:/project/app/controllers/Mustache_Logger.php' for inclusion (include_path='.;D:\project;C:\Program Files (x86)\Google\Cloud SDK\google-cloud-sdk\platform\google_appengine\php\sdk') in D:\project\index.php on line 5

Warning: include(D:/project/app/controllers/Mustache_Parser.php): failed to open stream: No such file or directory in D:\project\index.php on line 5

Warning: include(): Failed opening 'D:/project/app/controllers/Mustache_Parser.php' for inclusion (include_path='.;D:\project;C:\Program Files (x86)\Google\Cloud SDK\google-cloud-sdk\platform\google_appengine\php\sdk') in D:\project\index.php on line 5

Warning: include(D:/project/app/controllers/Mustache_Tokenizer.php): failed to open stream: No such file or directory in D:\project\index.php on line 5

Warning: include(): Failed opening 'D:/project/app/controllers/Mustache_Tokenizer.php' for inclusion (include_path='.;D:\project;C:\Program Files (x86)\Google\Cloud SDK\google-cloud-sdk\platform\google_appengine\php\sdk') in D:\project\index.php on line 5

Warning: include(D:/project/app/controllers/Mustache_Compiler.php): failed to open stream: No such file or directory in D:\project\index.php on line 5

Warning: include(): Failed opening 'D:/project/app/controllers/Mustache_Compiler.php' for inclusion (include_path='.;D:\project;C:\Program Files (x86)\Google\Cloud SDK\google-cloud-sdk\platform\google_appengine\php\sdk') in D:\project\index.php on line 5

Warning: include(D:/project/app/controllers/Mustache_Template.php): failed to open stream: No such file or directory in D:\project\index.php on line 5

Warning: include(): Failed opening 'D:/project/app/controllers/Mustache_Template.php' for inclusion (include_path='.;D:\project;C:\Program Files (x86)\Google\Cloud SDK\google-cloud-sdk\platform\google_appengine\php\sdk') in D:\project\index.php on line 5

Warning: include(D:/project/app/controllers/Mustache_Context.php): failed to open stream: No such file or directory in D:\project\index.php on line 5

Warning: include(): Failed opening 'D:/project/app/controllers/Mustache_Context.php' for inclusion (include_path='.;D:\project;C:\Program Files (x86)\Google\Cloud SDK\google-cloud-sdk\platform\google_appengine\php\sdk') in D:\project\index.php on line 5

Warning: include(D:/project/app/controllers/Mustache_HelperCollection.php): failed to open stream: No such file or directory in D:\project\index.php on line 5

Warning: include(): Failed opening 'D:/project/app/controllers/Mustache_HelperCollection.php' for inclusion (include_path='.;D:\project;C:\Program Files (x86)\Google\Cloud SDK\google-cloud-sdk\platform\google_appengine\php\sdk') in D:\project\index.php on line 5
Hello World!

Do you have any idea how to solve it? Thank you.


Solution

  • PHP tries every autoloader registered, in order, while trying to load a file. Once one autoloader successfully loads the file, it stops trying. In your case, it's trying the autoloader in index.php before trying the Mustache autoloader.

    And the autoloader in index.php is too naive:

    function autoloader($class)
    {
        include($_SERVER['DOCUMENT_ROOT'] . '/app/controllers/' . $class . '.php');
    }
    spl_autoload_register('autoloader');
    

    This code blindly calls include with whatever class name it's given, whether such a file exists or not. You can see from the output that it's trying to include a file inside controllers for every class used by Mustache.

    The code doesn't fail completely, because after your autoloader is unable to load the file, PHP tries the next registered autoloader (the one that came with Mustache) and that successfully loads the necessary file.

    You can fix your autoloader code by checking the existence of the file before including it. You can also make it a bit smarter by checking for a webpage\ namespace prefix on the class before trying to load the file.