How to Set Up a Document Root Folder Without Server Access

:file_folder: 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 to public/index.php unless it’s a static file.
  • .htaccess inside public/ to serve static files or rewrite everything else to index.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.


:card_index_dividers: 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

:wrench: 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]

:wrench: 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>

:brain: 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 to home-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.

:compass: 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);

:puzzle_piece: Example Controller

<?php
// controllers/home-page.controller.php

require __DIR__ . '/../views/home-page.view.php';

:framed_picture: Views & Partials

Views are the user-facing HTML templates. You can break them up into reusable partials for headers, footers, nav, etc.


:white_check_mark: Final Checklist

  • .htaccess in htdocs rewrites to public/index.php
  • Static files (CSS, JS, images) served from /public/
  • Routing handled in public/index.php via routes.php
  • Clean URLs enabled
  • Controllers and Views organized and secure

Thanks for reading, and happy coding! :+1:

2 Likes

This topic was automatically closed 15 days after the last reply. New replies are no longer allowed.