We have moved our forum to GitHub Discussions. For questions about Phalcon v3/v4/v5 you can visit here and for Phalcon v6 here.

HostUiController handler class cannot be loaded

Hi there,

I've started an application alond the lines of Tutorial 1 in the docs. Using XDebug, I can step through the code in my app_name/public/index.php but on this line:

echo $application->handle()->getContent();

I immediately hit the catch handler.

I've set up an IndexController.php in app/controller but this isn't hit as I've added breakpoints in there. What I've done is almost line for line based on the tutorial. I'm using nginx for my web server.

Any ideas what I might be doing wrong here?

Many thanks! :)

Paste your code please. Read: https://forum.phalcon.io/help/markdown - the last code block example gives you syntax highlighting.



38.8k
edited Apr '14
<?php

try {

    //Register an autoloader
    $loader = new \Phalcon\Loader();
    $loader->registerDirs(array(
        '../app/controllers/',
        '../app/models/'
    ))->register();

    //Create a DI
    $di = new Phalcon\DI\FactoryDefault();

    //Setup the view component
    $di->set('view', function(){
        $view = new \Phalcon\Mvc\View();
        $view->setViewsDir('../app/views/');
        return $view;
    });

    //Setup a base URI so that all generated URIs include the "tutorial" folder
    $di->set('url', function(){
        $url = new \Phalcon\Mvc\Url();
        $url->setBaseUri('/host_ui/');
        return $url;
    });

    //Handle the request
    $application = new \Phalcon\Mvc\Application($di);

    echo $application->handle()->getContent();

} catch (\Phalcon\Exception $e) {
    echo "PhalconException: ", $e->getMessage();
}


38.8k
edited Apr '14
<?php
class IndexController extends \Phalcon\Mvc\Controller
{

    public function indexAction()
    {
        echo "<h1>Hello!</h1>";
    }

}

What is the exception being thrown?

Also, I tweaked your post - added the "php" behind the backticks to get the highlighting. No biggie.



38.8k

Ah, sorry - I didn't notice the "php". Will know for future reference :)

The exception being thrown is:

PhalconException: HostUiController handler class cannot be loaded

Weird that "host_ui" in being involved there, as you've simply set it in your URL service. Try commenting out this:

$di->set('url', function(){
    $url = new \Phalcon\Mvc\Url();
    $url->setBaseUri('/host_ui/');
    return $url;
});

Just to see what happens.

I assume the URL you're trying to load is:

www.whateveryourdomainis.com/host_ui/public/index.php?



38.8k

I commented out the 'url' code and got the same result. On the basis that the documents say: "By default Phalcon will look for a controller named “Index”. It is the starting point when no controller or action has been passed in the request.", I simply have a URL of:

https://10.10.22.35/host_ui/test

My nginx config (below) setys the root path into 'public', so, I just typed any URL in just to get it to work.

server {
    listen       80;
    server_name  localhost;

    index       index.php index.html index.htm;
    set         $root_path '/mae/www/html';
    root        $root_path;

    location /host_ui/ {
        set $root_path "$root_path/host_ui/public";
        try_files $uri $uri/ @rewrite;
    }

    location @rewrite {
        rewrite ^/(.*)$ /index.php?_url=/$1;
    }

    # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
    location ~ \.php$ {
        fastcgi_pass   127.0.0.1:9000;
        fastcgi_index  index.php;
        fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name;
        include        fastcgi_params;
    }
}


125.8k
Accepted
answer

Hmmm, I think since you've set your root to the public directory, then when you load https://10.10.22.35/host_ui/test, you're actually loading https://10.10.22.35/public/index.php?_url=host_ui/test. Phalcon is then seeing that as controller = "host_ui", action = "test". Try just https://10.10.22.35/



38.8k

https://10.10.22.35/ just returns a 403 Forbidden from Nginx because there isn't a location defined to handle that Url.

Do you know, I hadn't even made the connection between the exception reported by Phalcon "HostUiController" and my "host_ui" URL! :)

So, Phalcon is seemingly, by convention, removing the underscore and putting the words together in Pascal case? Jeez, I thought I'd escaped Rails when I came back to PHP ;)

'host_ui' is the application's root folder, like 'tutorial' in the "Tutorial 1". So, I wouldn't want/expect 'host_ui' to be treated like a controller, particularly when it is also defined as the base Uri in the bootstrap code.

Is this a bug in Phalcon?

I'm pretty sure this isn't a bug in Phalcon... but I'm not 100% sure what the problem is yet. The URL service is just used for URL generation, it's not used by Phalcon to determine paths to application components, so that's not an issue.

I have no experience configuring Nginx, but I suspect the issue might be there. Why do you have this directory configured separately?

location /host_ui/ {
    set $root_path "$root_path/host_ui/public";
    try_files $uri $uri/ @rewrite;
}

If I understand it correctly (there's a good chance I don't), you don't need to re-set $root_path. The root of the server is still /mae/www/html, that doesn't need to change.



38.8k

Nginx location blocks are based on URLs so, this block handles any URL that follows this pattern: https://10.10.22.35/host_ui/

I have to specify the document root because the index.php that Phalcon uses is in the 'public' directory. I can't just use the base root path of '/mae/www/html' because in there, we have 'host' and 'host_ui' where 'host' is the base folder for a RESTful API (using a Phalcon Micro application). The 'host_ui' is intended to be a full stack application that also consumes services provided by the 'host' api. So, for all these reasons, it isn't obvious that '/mae/www/html' is the document root. It's just the first part of two document roots used by two different URLs.

At least in Apache-land, the document root is the document root of the server - that doesn't change depending on which directory you're in. Maybe it's different in Nginx land.

Right before your call to

echo $application->handle()->getContent();

Can you do a

print_r($_SERVER)

Just to see what the finally resultant URL and query strings are?



38.8k

In Apache, if you have a VirtualHost, you can specify whatever DocumentRoot you want. On the same host, you can have multiple VirtualHosts all with different DocumentRoot values.

In Nginx, the document root isn't dependent on directory. Like I mentioned, https://10.10.22.35/host_ui/ is not a directory, it's a URL. The Nginx location block responds to the URL. In the block that traps https://10.10.22.35/host_ui/ I then decide what the document root should be for requests that match that URI, just like you can in Apache. In Nginx, I don't have to specify a document root in a location block, it can be global to the server but the point is, it doesn't have to be, just like it doesn't have to be in Apache.

As far as Phalcon is concerned, the index.php is invoked by the rewrite in the appropriate document root of /mae/www/html/host_ui/public/index.php and Phalcon should be obvlivious to this fact. I'm starting to think that Phalcon might be getting confused by the underscore in the directory name.

Can any of the Phalcon authors comment on this?



38.8k

@quasipickle > Just to see what the finally resultant URL and query strings are?

I can't check until I get back in work tomorrow but from memory, the value in the _url parameter was/is 'host_ui/test' -- in that case, I guess Phalcon would just treat 'host_ui' as the controller, hence the behaviour I'm seeing. Maybe, I'll just have to alter the Nginx re-write RegEx so that 'host_iu' is stripped out of the re-written URL which in the current case would have just left 'test'.

Not knowing full-stack Phalcon at all, I imagine that you could also create specific routes that map to 'host_ui/...' but extract portions of the URL pattern beyond 'host_ui/' for the purpose of establishing controller/action/id. Does this sound feasible? Using the Phalcon Micro app was really easy because you explicilty specify a route. However, Tutorial 1 is using implicit route pattern analysis and that is perhaps where I'm having the issue. If I wanted to specify routes, does this dove-tail easily in to what I've already done or, is there a different approach I should follow?

Thanks for the help and advice you've give me. It's much appreciated :)

I think changing your rewrite makes the most sense. The content of the _url parameter is decided by your web server and the re-write logic before Phalcon is even loaded, so the problem doesn't seem to be Phalcon.

I don't know if you're at all familiar with Apache, but all my apps run with 2 .htaccess files. 1 file sits at the root of the app directory and redirects all requests to the public directory. The public directory has a second redirect file that redirects any requests for non-files to index.php?_url..... If I were seeing what you're seeing, it would mean my first redirection is one directory too high. I'm not sure how useful that information is, but thought I'd share.



38.8k

@quasipickle - Thanks for your help and advice with this. I managed to resolve the issue by stripping out 'host_ui' from the Nginx rewrite. I also posted the Nginx logging output showing the _url values when typing first, https://10.10.22.35/host_ui/ and then https://10.10.22.35/host_ui/test/name. So, all is well, it's not a Phalcon bug and my stress levels have dropped back to what they normally are! :) Cheers.

server {
    listen       80;
    server_name  localhost;

    index       index.php index.html index.htm;
    set         $root_path '/mae/www/html';
    root        $root_path;

    location /host_ui/ {
        set $root_path "$root_path/host_ui/public";
        try_files $uri $uri/ @host_ui_rewrite;
    }

    location @host_ui_rewrite {
        rewrite ^/host_ui/(.*)$ /index.php?_url=/$1;
    }

    # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
    location ~ \.php$ {
        fastcgi_pass   127.0.0.1:9000;
        fastcgi_index  index.php;
        fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name;
        include        fastcgi_params;
    }
}

2014/04/08 02:35:46 [notice] 26357#0: *1 rewritten data: "/index.php", args: "_url=/", client: 10.10.1.151, server: localhost, request: "GET /host_ui/ HTTP/1.1", host: “10.10.22.35"

2014/04/08 02:37:30 [notice] 26357#0: *6 rewritten data: "/index.php", args: "_url=/test/name", client: 10.10.1.151, server: localhost, request: "GET /host_ui/test/name HTTP/1.1", host: "10.10.22.35"

Ah, so it would appear the rewrite rules act from the document root of the server, not the location from which the rules are referenced.

Glad to hear it's working now.