Windows 10 - Wamp - PHP 7.2.18
With Phalcon V3, I can have multiple project at the root of the server like :
http://localhost/project/
http://localhost/project2/
...
With Phalcon V4, I get this error:
HelloWorld2Controller handler class cannot be loaded
#0 [internal function]: Phalcon\Mvc\Dispatcher->throwDispatchException('HelloWorld2Cont...', 2)
#1 [internal function]: Phalcon\Dispatcher\AbstractDispatcher->dispatch()
#2 E:\wamp64\www\hello_world2\public\index.php(45): Phalcon\Mvc\Application->handle('/hello_world2/')
#3 {main}
To solve temporary this issue, I updated the file public/index.php:
echo $application->handle($_SERVER['REQUEST_URI'])->getContent();
to
echo $application->handle(str_replace('hello_world2/','',$_SERVER['REQUEST_URI']))->getContent();
But, It's not very great.
@jenovateurs You're on Phalcon 4.0.0-RC.3?
@ruudboon Yes, I'm on Phalcon 4.0.0-rc.3.
@jenovateurs could you try to pass in $_GET["_url"]. That was the default in 3.4
$application->handle($_GET["_url"])->getContent();
@ruudboon When I tried with $_GET["_url"], I got this error :
Notice: Undefined index: _url in E:\wamp64\www\test\public\index.php on line 43
Fatal error: Uncaught TypeError: Argument 1 passed to Phalcon\Mvc\Application::handle() must be of the type string, null given in E:\wamp64\www\test\public\index.php on line 43
@jenovateurs And you are using the same Apache or Nginx config as your 3.4 environment? I did some comparison between 4 and 3.4 on this point I don't see any changes that could cause this behaviour. Also on my test machine I was able to run directory based on the $_GET["_url"] (using nginx).
@ruudboon Yes, I used the same Apache configuration. I just changed the Phalcon extension.
I took a project created with v3 and I have no problem. But when I put the parameter $_SERVER['REQUEST_URI'] in the handle function, it's like I'm always in the indexAction. No error is triggered even if I add some parameters in the URI.
When I took a v4 project, I had the same error :
TestController handler class cannot be loaded
But when I deleted $_SERVER['REQUEST_URI'] from handle, I had a normal error:
Uncaught Error: Class 'Phalcon\Url' not found in
When I called this URL: http://127.0.0.1/test/with Apache
$_SERVER['REQUEST_URI'] return /test/
With Nginx, do you have the same value ?
@jenovateurs Nginx will strip out the dir. Config looks something like this. $1 will only hold the part after the '/'. I will have a look at this with apache.
location / {
try_files $uri $uri/ @rewrite;
}
location @rewrite {
rewrite ^(.*)$ /index.php?_url=$1;
}
@ruudboon
Thanks for the Nginx information.
I think, I have understood the problem.
When I called this URL : http://127.0.0.1/test/
$_GET['_url'] was null and it's generated an error because handle expected a non-null value.
When I called this URL : http://127.0.0.1/test/utilisateur
$_GET['_url'] wasn't null and worked well.
So now, I do that:
echo $application->handle($_GET['_url'] ?? '/')->getContent();
What do you think ?
I found this solution by reading the code of the router in v3 : https://github.com/phalcon/cphalcon/blob/3.4.x/phalcon/mvc/router.zep
I saw this function :
public function getRewriteUri() -> string
{
var url, urlParts, realUri;
/**
* By default we use $_GET["url"] to obtain the rewrite information
*/
if !this->_uriSource {
if fetch url, _GET["_url"] {
if !empty url {
return url;
}
}
} else {
/**
* Otherwise use the standard $_SERVER["REQUEST_URI"]
*/
if fetch url, _SERVER["REQUEST_URI"] {
let urlParts = explode("?", url),
realUri = urlParts[0];
if !empty realUri {
return realUri;
}
}
}
return "/";
}
And if I understand well, if $_GET['_url']is null, the function returns '/'.
So is it an issue concerning the generation of projects with phalcon/devtools ?
Need to change$_SERVER['REQUEST_URI'] to $_GET['_url'] ?? '/'?
Good catch. I think we need to allow null on the handle. Let me double check and patch that.
Resolved in https://github.com/phalcon/cphalcon/pull/14576
@ruudboon I'm sorry but I didn't understand the fix code. The parameter uri is still required in the handle function.
Then, when I used $_SERVER["REQUEST_URI"], I got the same error. And $_GET['_url'] isn't defined when you call this url : http://127.0.0.1/test/ (Root project)
To test it, I compiled the last version of v4.0.x on Debian.
@jenovateurs It was already optional. But we didn't fall back '/'. That's what is changed now. So we now handle it in the same way 3.4 does.
The handeling of the non existing key in the global is array is currently handled outside the framework. So that should be handled inside your project. For example $_GET['_url'] ?? null or $_GET['_url'] ?? ''.
Currently I don't see any other options besides this. @niden do you have any thoughts on this?
We should mention this more clear in the docs.
@ruudboon When I used the function handle like that :
$application->handle($_GET['_url'] ?? null)->getContent();
I had this error:
Fatal error: Uncaught TypeError: Argument 1 passed to Phalcon\Mvc\Application::handle() must be of the type string, null
In v3, we have:
public function handle(string uri = null)
In v4, we have:
public function handle(string! uri) -> void
If I understand well the v4 code, uri is required and null isn't an acceptable value.
About $_GET['_url'] ?? '', do you think phalcon/devtools need to be update ?
Besides, I was thinking about baseUriproperty in the config file. I tried to replace
'baseUri' => preg_replace('/public([\/\\\\])index.php$/', '', $_SERVER["PHP_SELF"]),
by
'baseUri' => '/test/',
And it changes nothing.
I also saw that in phalcon/devtools the line
'baseUri' => preg_replace('/public([\/\\\\])index.php$/', '', $_SERVER["PHP_SELF"]),
was replaced by
'baseUri' => '/',
With this modification, urls are wrong. In order to get correct url, I need to add /test/ in the baseUri. But with the old way:
'baseUri' => preg_replace('/public([\/\\\\])index.php$/', '', $_SERVER["PHP_SELF"]),
I had no problem.
I think that there is another solution: using baseUri in the handle function.
@ruudboon Is it normal that the issue is still closed ? Thanks ;-)
I will discuss this with the team to decide if we need to allow null as well.
Moving this to 4.1. Need to think this through more.
@niden No problem, I understand.
Hi, everyone.
I was having this same issue when creating a project in a subfolder. I saw some good solutions, but I tried to solve it with an improvement: use the base directory to determine the full subfolder path and use it as a "pseudo-root" folder for the project. All I did was to replace (in _public/index.php_) this line:
echo $application->handle($_SERVER['REQUEST_URI'])->getContent();
with these lines:
$path = str_replace($_SERVER["DOCUMENT_ROOT"], '', str_replace("\", "/", BASE_PATH));
$uri = str_replace($path, '', $_SERVER['REQUEST_URI']);
echo $application->handle($uri)->getContent();
I tested it with up to 2 levels of subfolders, but I think it can work with more levels. It also works with the project in the root directory of the web server.
If this solution is useful to you, please, let me know.