Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[BUG]: v4 Regression - localhost/project/ - trouble with Application->handle #14559

Open
jenovateurs opened this issue Nov 27, 2019 · 20 comments
Assignees
Labels
5.0 The issues we want to solve in the 5.0 release bug A bug report documentation Documentation required status: medium Medium

Comments

@jenovateurs
Copy link
Contributor

jenovateurs commented Nov 27, 2019

Config

Windows 10 - Wamp - PHP 7.2.18

Description

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}

Little hack

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.

@ruudboon
Copy link
Member

ruudboon commented Nov 29, 2019

@jenovateurs You're on Phalcon 4.0.0-RC.3?

@jenovateurs
Copy link
Contributor Author

@ruudboon Yes, I'm on Phalcon 4.0.0-rc.3.

@ruudboon
Copy link
Member

@jenovateurs could you try to pass in $_GET["_url"]. That was the default in 3.4

$application->handle($_GET["_url"])->getContent();

@jenovateurs
Copy link
Contributor Author

@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

@ruudboon
Copy link
Member

ruudboon commented Dec 2, 2019

@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).

@jenovateurs
Copy link
Contributor Author

@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 ?

@ruudboon
Copy link
Member

ruudboon commented Dec 2, 2019

@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;
}

@jenovateurs
Copy link
Contributor Author

@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'] ?? '/' ?

@ruudboon
Copy link
Member

ruudboon commented Dec 2, 2019

Good catch. I think we need to allow null on the handle. Let me double check and patch that.

@niden
Copy link
Member

niden commented Dec 3, 2019

Resolved in #14576

@niden niden closed this as completed Dec 3, 2019
@jenovateurs
Copy link
Contributor Author

@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.

@ruudboon
Copy link
Member

ruudboon commented Dec 3, 2019

@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 ruudboon added the documentation Documentation required label Dec 3, 2019
@jenovateurs
Copy link
Contributor Author

jenovateurs commented Dec 3, 2019

@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 baseUri property 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.

@jenovateurs
Copy link
Contributor Author

@ruudboon Is it normal that the issue is still closed ? Thanks ;-)

@ruudboon
Copy link
Member

ruudboon commented Dec 11, 2019

I will discuss this with the team to decide if we need to allow null as well.

@niden
Copy link
Member

niden commented Dec 21, 2019

Moving this to 4.1. Need to think this through more.

@jenovateurs
Copy link
Contributor Author

@niden No problem, I understand.

@omega-the-loner
Copy link

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.

@Jeckerson Jeckerson added 4.1.1 The issues we want to solve in the 4.1.1 release and removed 4.1.0 labels Dec 14, 2020
@Jeckerson Jeckerson added 5.0 The issues we want to solve in the 5.0 release and removed 4.1.1 The issues we want to solve in the 4.1.1 release labels Mar 26, 2021
@gwijnja
Copy link

gwijnja commented Jul 18, 2021

I have been looking into this issue as well, this weekend. My conclusion is that you can not put your project in a subdirectory without adjusting the REQUEST_URI before it is passed to the application (which in turn passes it unaltered to the router.)

For example, a project called 'store' in a userdir, and another in a subdirectory under /var/www/html:

Path URL Expected URI Actual URI
/home/john/public_html/store https://192.168.0.2/~john/store/ / /~john/store/
/var/www/html/foo/store/users https://192.168.0.2/foo/store/users /users /foo/store/users

("Expected" means: expected by the router)

The Phalcon router tries to match them against the default routes, which never match a uri with a tilde (~) in it, so any url under a userdir results in the default index page. The second example, with the subdirectory under /var/www/html, will result in an error: "FooController handler class cannot be loaded", because 'foo' is the first part of the uri, while you would expect it to look for the UsersController.


A simple solution is to use $_SERVER['PHP_SELF'], which always contains the path to the running script. Within Phalcon it always points to index.php, for example in the cases above it points to /~john/store/public/index.php and to /foo/store/public/index.php. You can use this to determine the base uri (/~john/store/ or /foo/store/), which you can then strip off of $_SERVER['REQUEST_URI'] and get a clean uri that the router can work with.

In public/index.php, simply replace this line:

echo $application->handle($_SERVER['REQUEST_URI'])->getContent();

with these lines:

$baseUri = str_replace('/public/index.php', '', $_SERVER['PHP_SELF']);
$uri = str_replace($baseUri, '', $_SERVER['REQUEST_URI']);
echo $application->handle($uri)->getContent();

Pros:

  • Works with any subdirectory
  • No .htaccess changes needed
  • No custom routes needed

Cons:

  • Not part of the compiled zephir code

Disclaimer: only tested with cphalcon 4.1.2 and 5.0.0alpha3, devtools 4.1.1, with Apache, on CentOS 8.

@niden niden moved this to Active Sprint Tasks in Phalcon v5 Aug 25, 2022
@niden niden added this to Phalcon v5 Aug 25, 2022
@mesaglam
Copy link

mesaglam commented Dec 4, 2024

Hi, I've done the modification above but no luck. Getting indexController handler class cannot be loaded error. Same code is working another server with same config. I couldn't get it...

  • PHP Version 7.4.33,
  • Phalcon 4.1.2,
  • Nginx 1.18.0

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
5.0 The issues we want to solve in the 5.0 release bug A bug report documentation Documentation required status: medium Medium
Projects
Status: Active Sprint
Development

No branches or pull requests

7 participants