Site structure

A site has a small, fixed shape: a web root with one entry point, a configuration file kept above the web root, the site's own modules, and any data it seeds on first run. The shared framework modules sit alongside it. Learn this shape once and every site looks the same.

The site folder

A site folder holds four things. Everything the browser can reach lives under public_html; everything else stays outside it.

site/
  Config.php              non-secret configuration constants (never web-served)
  public_html/            the web root Apache serves
    index.php             the one entry point: include and run the modules
    stylesheet.css        static assets are served directly
    js/
    images/
  php_modules/            modules written for this site
    Shop/
  install/                data this site seeds on first run
    0001.php

Config.php

Config.php holds the site's non-secret configuration as plain constants: where the framework modules are, the site title, the default admin account, and similar settings. It lives above public_html so it is never served to a browser. The entry point includes it first, before any module. The Configuration page covers what goes in it and how secrets are handled separately.

public_html

public_html is the only folder the web server exposes. It contains index.php, the front controller that every request reaches, plus the static assets the pages link to, such as a stylesheet, scripts and images. Those files are served directly by Apache; everything dynamic is produced by the modules that index.php includes.

The entry point sets a few globals, provides configuration, includes the modules, and hands control to the framework's routing. The Configuration and Routing pages walk through it in full.

php_modules

The site's own modules live in php_modules. A site-specific module, such as a Shop, has exactly the same shape as a framework module: an index file, a class folder, a data folder, a database folder, an install folder and a config class. The Module layout page describes that shape in detail.

install

A site often needs a little data in place on first run: a starting category, a settings row, a home page record. That data is seeded the same way a module seeds its own, through numbered scripts in the site's install folder, run by one call in the entry point:

Database::Install('App', __DIR__ . '/../install', 1);

This is the site acting like a module for its own data. The Migrations and seed data page explains how the numbered scripts work and how production data and example data are kept apart.

The framework modules

The shared framework modules are not copied into the site. They sit in their own folder and are mounted alongside it, so many sites share one copy. In the Docker setup the framework is mounted at /var/www/framework and the site at /var/www/site.

The entry point records the framework path in a global, $MODULE_PATH. A module reaches another framework module through that path, and reaches a site module through a path relative to itself:

// a framework module, via $MODULE_PATH
require_once $MODULE_PATH . '/Database/index.php';

// a site module, relative to the file doing the including
require_once __DIR__ . '/../php_modules/Shop/index.php';

Shared modules and site modules

A module lives in one of two places, decided by how widely it is used:

  • a module reused across sites, including the framework's own, lives in a shared modules folder mounted into each site,
  • a module specific to one site lives in that site's php_modules folder.

The two are identical in structure and are written the same way. Only the location differs, and a module can graduate from a site into a shared batch later without changing its shape. You can also keep your own shared batch of modules, separate from the framework's, and mount it the same way.

Next: Configuration.