Skip to main content

Static Files with Modern Routing

Serve static assets (CSS, JavaScript, images, fonts, etc.) directly from a folder with automatic MIME type detection and caching headers.

Basic Usage​

<?php
require_once 'vendor/autoload.php';

use PhpCompatible\Router\Router;

Router::run(function() {
// Serve static files from /assets folder at /assets URL
Router::staticFolder(__DIR__ . '/assets', '/assets');

Router::get('/', function() {
return 'Home';
});
});

URL Mapping​

The Router::staticFolder() method maps URL paths to files in your static folder:

/public/
├── css/
│ └── style.css → /assets/css/style.css
├── js/
│ └── app.js → /assets/js/app.js
├── images/
│ └── logo.png → /assets/images/logo.png
└── fonts/
└── roboto.woff2 → /assets/fonts/roboto.woff2

Options​

Cache Control​

By default, static files are cached for 24 hours. Customize this:

use PhpCompatible\Router\Router;

Router::run(function() {
// Cache for 1 week
Router::staticFolder(__DIR__ . '/public', '/assets', array(
'cache_time' => 604800
));

// No caching (development)
Router::staticFolder(__DIR__ . '/public', '/assets', array(
'cache_time' => 0
));

// Cache for 1 year (versioned assets)
Router::staticFolder(__DIR__ . '/public', '/assets', array(
'cache_time' => 31536000
));
});

Allowed Extensions​

Restrict which file types can be served:

Router::run(function() {
// Only serve CSS, JS, and images
Router::staticFolder(__DIR__ . '/public', '/assets', array(
'allowed_extensions' => array('css', 'js', 'png', 'jpg', 'gif', 'svg', 'webp')
));

// Only serve fonts
Router::staticFolder(__DIR__ . '/fonts', '/fonts', array(
'allowed_extensions' => array('woff', 'woff2', 'ttf', 'otf', 'eot')
));
});

Multiple Static Folders​

use PhpCompatible\Router\Router;

Router::run(function() {
// Serve different asset types from different folders
Router::staticFolder(__DIR__ . '/assets/css', '/css');
Router::staticFolder(__DIR__ . '/assets/js', '/js');
Router::staticFolder(__DIR__ . '/assets/images', '/images');
Router::staticFolder(__DIR__ . '/node_modules', '/vendor', array(
'allowed_extensions' => array('css', 'js', 'map')
));

// Application routes
Router::get('/', function() {
return '<link rel="stylesheet" href="/css/style.css">';
});
});

Complete Example​

<?php
require_once 'vendor/autoload.php';

use PhpCompatible\Router\Router;

Router::run(function() {
// Static assets
Router::staticFolder(__DIR__ . '/public', '/assets');

// API routes
Router::group('/api', function() {
Router::get('/users', function() {
return array('users' => array());
});
});

// Web routes
Router::get('/', function() {
return file_get_contents(__DIR__ . '/views/home.html');
});
});

Project Structure​

/myapp
├── public/
│ └── index.php # Entry point
├── assets/
│ ├── css/
│ │ └── style.css
│ ├── js/
│ │ └── app.js
│ └── images/
│ └── logo.png
├── views/
│ └── home.html
└── vendor/

Security​

The Router::staticFolder() method includes security measures:

Directory Traversal Prevention​

Attempts to access files outside the static folder are blocked:

// URL: /assets/../../../etc/passwd
Router::staticFolder(__DIR__ . '/public', '/assets');
// Result: 404 Not Found

Real Path Validation​

The function uses realpath() to resolve symbolic links and ensure files are within the allowed folder.

MIME Types​

The router automatically detects MIME types based on file extension:

ExtensionMIME Type
.csstext/css
.jstext/javascript
.jsonapplication/json
.pngimage/png
.jpgimage/jpeg
.svgimage/svg+xml
.woff2font/woff2

Production Web Server​

For production, configure your web server to serve static files directly for better performance.

Apache​

RewriteEngine On

# If the file exists in assets, serve it directly
RewriteCond %{REQUEST_FILENAME} -f
RewriteRule ^assets/(.*)$ assets/$1 [L]

# Otherwise, route to PHP
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php?url=$1 [QSA,L]

Nginx​

location /assets {
alias /var/www/html/assets;
expires 1y;
add_header Cache-Control "public, immutable";
}

location / {
try_files $uri $uri/ /index.php?url=$uri&$args;
}