I come from a C# MVC background but I am currently working on a PHP project.
In C# you can setup decorators to specify the request URL using something along these lines:
[HttpGet]
[Route("/ControllerName/ActionName")]
public string MyAction() {
// ...
}
I am wanting to set something similar up in PHP, so I set my file structure like this:
+ assets
+ css
+ javascript
+ images
+ server
+ api
+ controllers
- index.php
+ ui
+ area1
- view1.html
- view2.html
+ area2
- etc.html
- .htaccess
- index.html
Where index.html is my login page, the other html pages live in their respective /ui/area
directory, and my restful API pages live in /server/api/controllers
. The /server/api/index.php
follows a very similar pattern to this Stack Overflow answer: https://stackoverflow.com/a/1737903/1920035
In my .htaccess
file, I have the following redirect rule setup:
# Redirect traffic starting with /api to the /server/api/index.php file
Redirect 301 ^(api/.*)$ /server/api/index.php [L,QSA]
The idea is that if I hit /api/account/get
that it will redirect to the /server/api/index.php
file and run its magic to run the respective controller/action.
The issue is that when I spin up my server and hit the pretty URL that it always returns a 500 response without any useful response text.
To complicate things, I'm running Docker for Windows using php:8.2.2-apache.
What am I doing wrong here? I do not have much experience setting up .htaccess files and with a vague 500 response, I don't have much to go off of.
You need to check Apache's error log for the details of the 500 error. However...
Redirect 301 ^(api/.*)$ /server/api/index.php [L,QSA]
This is syntactically invalid (which might account for the 500 error) and the wrong directive to use here. Redirect
is a mod_alias directive that triggers an external redirect. [L,QSA]
are "flags" used with the mod_rewrite RewriteRule
directive. The Redirect
directive does not take a regex as an argument (it uses simple prefix-matching).
But you shouldn't be triggering an HTTP external (301) redirect here, you need to internally rewrite the request instead (the user should not be aware of the underlying /server
subdirectory).
For this (URL rewriting) you need to use mod_rewrite (so this needs to be installed if not already). For example:
RewriteEngine On
RewriteRule ^api/ server/api/index.php [L]
A request for /api/<anything>
would be internally rewritten to /server/api/index.php
.
No need for the capturing group and .*
suffix on the original regex. So, ^api/
is essentially the same as ^(api/.*)$
, but more efficient. The slash prefix on the substitution string (2nd argument) is not required with internal rewrites (and best omitted - so it is treated as a filesystem path and not a URL-path).
mod_rewrite (RewriteRule
/ RewriteCond
directives) is capable of issuing (complex) external redirects as well as internal rewrites. mod_alias (Redirect
/ RedirectMatch
directives) is for simple external redirects only. (Having said that, mod_alias also has some directives used for internal filesystem mapping.)
Reference: