How to Set Up a Document Root Folder Without Server Access
TL;DR
If you can’t change the actual Apache DocumentRoot
, simulate one using:
- A
public/
folder for your public files (CSS, JS, images, index.php). .htaccess
in the project root to rewrite everything topublic/index.php
unless it’s a static file..htaccess
insidepublic/
to serve static files or rewrite everything else toindex.php
.- A basic router in
index.php
to direct requests to the right controller. - Use clean URLs like
/home
,/recipes
, etc., instead of exposing file paths.
Intro - How To Set up a Document Root Folder
If you’re asking “how do I set up a document root folder when I have no control over the server configuration?”, this guide will help.
We’ll simulate a proper DocumentRoot
by serving all public files from a public/
directory while keeping controllers, views, and other logic out of it.
Directory Structure
htdocs - # project root
│ .htaccess
│ db_connect.php
│ db_query.php
│ functions.php
│
├───controllers
│ contact-form.controller.php
│ home-page.controller.php
│ recipes.controller.php
│ routes.php
│
├───public - # document root
│ │ .htaccess
│ │ index.php
│ │
│ ├───images
│ ├───scripts
│ └───styles
│
└───views
│ contact-form.view.php
│ home-page.view.php
│ recipes.view.php
│
└───partials
body.view.php
footer.php
nav.view.php
banner.view.php
Root .htaccess
Configuration (htdocs/.htaccess
)
RewriteEngine On
# Allow access to public static assets
RewriteCond %{REQUEST_URI} ^/(styles|scripts|images|favicon\.ico|robots\.txt)
RewriteRule ^(.*)$ public/$1 [L]
# Redirect root to a route (e.g., /home)
RewriteRule ^$ /home [L,R=301]
# Skip rewrite if file or folder exists
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
# Rewrite all other requests to front controller
RewriteRule ^ /public/index.php [L,QSA]
Public .htaccess
Configuration (public/.htaccess
)
<IfModule mod_rewrite.c>
RewriteEngine On
# Serve existing static files directly
RewriteCond %{REQUEST_FILENAME} -f [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^ - [L]
# Otherwise, route to index.php
RewriteRule ^ index.php [QSA,L]
</IfModule>
Explanation of Key Rules
- Static File Access: Let assets like
/images/foo.webp
or/styles/app.css
be served directly. - Friendly URLs:
/home
gets routed tohome-page.controller.php
, not/controllers/home-page.controller.php
. - Prevent 403 Errors: Root requests (
/
) redirected to a defined route (/home
). - Fallback Routing: All other paths go to
public/index.php
.
Basic Router Example (controllers/routes.php
)
<?php
$uri = parse_url($_SERVER['REQUEST_URI'])['path'];
$routes = [
'/' => __DIR__ . '/home-page.controller.php',
'/home' => __DIR__ . '/home-page.controller.php',
'/recipes' => __DIR__ . '/recipes.controller.php',
'/contact' => __DIR__ . '/contact-form.controller.php',
];
function routeToController($uri, $routes)
{
if (array_key_exists($uri, $routes)) {
require $routes[$uri];
} else {
http_response_code(404);
echo '404 Not Found';
}
}
routeToController($uri, $routes);
Example Controller
<?php
// controllers/home-page.controller.php
require __DIR__ . '/../views/home-page.view.php';
Views & Partials
Views are the user-facing HTML templates. You can break them up into reusable partials for headers, footers, nav, etc.
Final Checklist
-
.htaccess
inhtdocs
rewrites topublic/index.php
- Static files (CSS, JS, images) served from
/public/
- Routing handled in
public/index.php
viaroutes.php
- Clean URLs enabled
- Controllers and Views organized and secure
Thanks for reading, and happy coding!