Download the PHP package unirend/php-static-server without Composer

On this page you can find all versions of the php package unirend/php-static-server. It is possible to download/install these versions without Composer. Possible dependencies are resolved automatically.

FAQ

After the download, you have to make one include require_once('vendor/autoload.php');. After that you have to import the classes with use statements.

Example:
If you use only one package a project is not needed. But if you use more then one package, without a project it is not possible to import the classes with use statements.

In general, it is recommended to use always a project to download your libraries. In an application normally there is more than one library needed.
Some PHP packages are not free to download and because of that hosted in private repositories. In this case some credentials are needed to access such packages. Please use the auth.json textarea to insert credentials, if a package is coming from a private repository. You can look here for more information.

  • Some hosting areas are not accessible by a terminal or SSH. Then it is not possible to use Composer.
  • To use Composer is sometimes complicated. Especially for beginners.
  • Composer needs much resources. Sometimes they are not available on a simple webspace.
  • If you are using private repositories you don't need to share your credentials. You can set up everything on our site and then you provide a simple download link to your team member.
  • Simplify your Composer build process. Use our own command line tool to download the vendor folder as binary. This makes your build process faster and you don't need to expose your credentials for private repositories.
Please rate this library. Is it a good library?

Informations about the package php-static-server

unirend/php-static-server

Packagist Version Packagist Downloads

Current version: 0.1.1

Serve Unirend SSG output on shared hosting (cPanel, Apache). Mirrors StaticWebServer from the Node.js package. It reads the same page-map.json format, serves clean URLs, handles 404/500 error pages with correct status codes, range requests, and custom API routes.

Requirements

Installation

Quick Start

  1. Build your Unirend SSG project. This produces a build/client/ directory with page-map.json inside.

  2. Copy the templates into your hosting document root:

  3. Edit index.php to point at your build directory:

  4. Deploy index.php, .htaccess, vendor/, and build/client/ to your host.

Options

Option Type Default Description
buildDir string required Absolute path to your SSG build directory
pageMapPath string 'page-map.json' Path to page map, relative to buildDir
singleAssets array [] Map individual files (favicon, robots.txt, etc.), merged with page map, takes precedence on conflicts with page map and asset folders
assetFolders array [] URL prefix → directory mappings for asset folders. A value can also be a ['path' => ..., 'detectImmutableAssets' => ...] array to set immutable detection per folder
notFoundPage string\|null null Custom 404 page path, relative to buildDir
errorPage string\|null null Custom 500 page path, relative to buildDir
cacheControl string 'public, max-age=0, must-revalidate' Cache-Control for HTML pages
immutableCacheControl string 'public, max-age=31536000, immutable' Cache-Control for hashed assets
isDevelopment bool false Show stack traces in default 500 error page HTML
logErrors bool true Enable error_log() as the fallback when no onError hook is set (or when the hook throws)
onError callable\|null null Custom error hook called with (\Throwable $e, string $context). Fires regardless of logErrors. If the hook throws, falls back to error_log() only if logErrors is true.

singleAssets

Map individual URLs to files, useful for robots.txt, favicon.ico, etc.

assetFolders

Map URL prefixes to asset directories. Files with content hashes in their names (e.g. app.abc123ef.js) automatically get immutable Cache-Control headers when detection is on for that folder.

Detection resolves per folder, mirroring StaticWebServer from the Node.js package: the per-folder value if you set one, otherwise the name-based default. That default is on for /assets (Vite's hashed build output) and off for every other folder, since those usually hold verbatim public/ files where a name that merely looks hashed must not get a year-long immutable header. There is no top-level flag, so passing detectImmutableAssets at the top level throws. Detection is a filename heuristic: a dot or dash followed by a run of 6 or more characters from the base64url alphabet that contains at least one digit or uppercase letter, then another dot. Plain lowercase words like some-multi-word.txt or apple-touch-icon.png therefore do not match, though rarer false positives are still possible when a name segment does contain a digit or uppercase letter, such as an all-caps word with digits like report-CHAPTER2.pdf. The reverse miss is accepted too: a rare all-lowercase real hash (well under 0.1% of outputs) is indistinguishable from a word, so it falls back to the regular cache header rather than risking names like chunk-vendors.js being cached as immutable. Only opt a folder in when it genuinely contains fingerprinted files.

OS metadata files are never served from a folder mount. A request that resolves to a junk name (macOS .DS_Store and ._* AppleDouble files, Windows Thumbs.db, ehthumbs.db, desktop.ini, and the rest) returns 404 before touching disk, matching StaticWebServer from the Node.js package. Folder mounts resolve the file straight from the URL, so a junk file that slips into a declared folder (SSG copies public/ verbatim into the build) would otherwise be reachable. Every path segment is checked, not just the basename, so a file routed through an OS metadata directory like /assets/.AppleDouble/metadata is blocked even though metadata is not itself junk, and a junk-named mount prefix cannot launder junk either. This filter is folder-only. An explicit singleAssets entry is an exact-match opt-in, so it is honored even when its URL is a junk name, the sole escape hatch.

Error Pages

Error pages are loaded at startup using the same priority chain as the Node.js StaticWebServer:

  1. /404 or /500 entry in page-map.json (your SSG-generated error page)
  2. notFoundPage / errorPage option
  3. 404.html / 500.html in buildDir
  4. Built-in generic HTML fallback

If your SSG generates /404 or /500 pages, they are automatically removed from the normal route map so they can only be served via error handlers with the correct status codes.

Error Logging

Default Behavior (logErrors: true)

By default, exceptions are written to PHP's error log via error_log() before displaying error pages:

Custom Error Hook (onError)

Use onError to route errors to your own logging system instead of error_log(). The hook receives the exception and a context string describing where the error occurred (e.g. 'Custom route handler error'):

If the hook itself throws, the error is silently caught and error_log() is used as a fallback (unless logErrors: false). The 500 response is still sent correctly.

Disabling error_log() Fallback

Set logErrors: false to disable the built-in error_log() fallback. A custom onError hook will still fire if one is provided. logErrors only controls whether error_log() is used:

To suppress all error logging entirely, set logErrors: false and omit onError.

Error pages are always displayed normally regardless of logging configuration.

PHP Error Log Location

Where error_log() writes depends on your PHP and server configuration:

Custom Routes

Add API endpoints or other server-side logic before calling serve(). Custom routes are checked before static file lookup, so they can also override static pages if needed.

Note: Custom route handlers are responsible for setting their own headers (Content-Type, Cache-Control, etc.). Only static files served from the page map or asset folders get automatic cache headers.

Route Path Normalization

Routes are automatically normalized for convenience:

Design Note: This is more forgiving than the default TypeScript/Fastify implementation. Since PHP executes per-request rather than as a long-running server, we normalize paths instead of throwing errors to avoid production outages from configuration mistakes.

Request Body Parsing

The $body parameter in route handlers is parsed automatically based on the request's Content-Type:

Range Requests

Supports HTTP range requests for video/audio seeking and resumable downloads. Single-range requests (Range: bytes=0-499, Range: bytes=500-, Range: bytes=-500) return 206 Partial Content. Multipart range requests are not supported and return 416 Range Not Satisfiable.

.htaccess

The included .htaccess routes all requests through index.php:

Note there is no !-f condition. This means raw .html files are never served directly by Apache. All requests go through index.php. This prevents React hydration mismatches that would occur if a user accessed /about.html instead of /about.

Local Development

PHP's built-in server works for local testing (.htaccess rules don't apply, but all requests go through index.php automatically).

Versioning

This package is versioned independently from the unirend npm package. It targets a specific use case (PHP shared hosting) and changes less frequently, so version numbers will not match between the two.

Changelog

Runs oldest to newest. The 0.0.x line was early iteration that was not logged per version, so entries start at 0.1.0.

0.1.0 (July 16, 2026)

0.1.1 (July 20, 2026)

Contributing to unirend-php

The canonical source for this package is the unirend monorepo, open issues and PRs there. Changes should be made in the main Unirend repo first, then published separately to the github.com/keverw/unirend-php mirror that Packagist reads from. Do not commit to the mirror directly except as part of the publish process.

Running Tests

From the monorepo root:

Install PHP dependencies (first time, or after dependency changes):

Run tests:

Running the Demo Locally

A minimal demo site is included in the monorepo under unirend-php/demo/ for development and testing purposes. It exercises clean URLs, a custom 404, an immutable-cached asset, and custom routes.

Note: The demo is not included in the published Composer package. It's only available in the monorepo.

Open http://localhost:8080 and explore the links listed on the home page.

Publishing a New Version

  1. Update unirend-php/version.json with the new version number.
  2. Run the publish script from the monorepo root:

The script clones the mirror repo, syncs files (excluding vendor/, demo/, version.json, etc.), updates the version line in this README, commits Release vX.Y.Z, tags it, and pushes. That triggers Packagist to update automatically via webhook.

License

MIT


All versions of php-static-server with dependencies

PHP Build Version
Package Version
Requires php Version ^8.1
Composer command for our command line client (download client) This client runs in each environment. You don't need a specific PHP version etc. The first 20 API calls are free. Standard composer command

The package unirend/php-static-server contains the following files

Loading the files please wait ...