PHP-SF uses a config/constants.php file for application-level configuration. This file is not committed to version control — config/constants.example.php is the committed template, and each environment has its own constants.php.
This is separate from .env by design: .env holds infrastructure credentials (database URLs, cache hosts, API keys), while constants.php holds application behaviour that is the same across all developers on a project but may differ between environments.
cp config/constants.example.php config/constants.php
The installer does this automatically. If the file is missing, the application will fail immediately on boot with a PHP fatal error since these constants are required before anything else loads.
These must be defined for the application to boot. Leaving any of them commented out or undefined will cause a fatal error.
DEV_MODEconst DEV_MODE = true;
The single most important constant. Controls a significant amount of framework behaviour:
When true |
When false |
|---|---|
| APCu cache is cleared on every request boot | APCu persists between requests |
| Route list is parsed from controllers on every request | Routes are cached in Redis indefinitely |
Template cache is bypassed regardless of TEMPLATES_CACHE_ENABLED |
Template cache respects TEMPLATES_CACHE_ENABLED |
Symfony Debug::enable() is called |
No debug handler |
| Translation strings are scanned and updated on every request | Translations are loaded from Redis cache |
| Query builder cache is not used | Query builder results are cached |
Set true in development, false in production. Never deploy with DEV_MODE = true.
TEMPLATES_CACHE_ENABLEDconst TEMPLATES_CACHE_ENABLED = false;
When true, compiled PHP template classes are cached in Redis. The cache strips HTML comments, collapses whitespace, removes optional closing tags, and stores the result. This meaningfully reduces template render time in production.
Has no effect when DEV_MODE = true — template caching is always bypassed in dev mode regardless of this value.
Recommended values: false in development, true in production.
DEFAULT_TIMEZONEconst DEFAULT_TIMEZONE = TimeZone::ETC_UTC;
Sets the default timezone used by the framework's DateTime class. Uses the TimeZone helper class constants — a full list of all available timezones is in PHP_SF\System\Classes\Helpers\TimeZone.
Examples:
const DEFAULT_TIMEZONE = TimeZone::ETC_UTC; // UTC
const DEFAULT_TIMEZONE = TimeZone::PL['warsaw']; // Europe/Warsaw
const DEFAULT_TIMEZONE = TimeZone::US['new_york']; // America/New_York
SERVER_IPconst SERVER_IP = '127.0.0.1';
The IP address of your server. Used in AVAILABLE_HOSTS to control which IPs can access API-only and cron endpoints protected by the api_example and cron_example middleware (or any custom middleware that checks AVAILABLE_HOSTS). In production, set this to your actual server's public or internal IP.
APPLICATION_NAMEconst APPLICATION_NAME = 'Your App Name';
Used as the default page title via pageTitle() and in the <title> tag in the default header template. Can be overridden per-page by passing a title to $this->render().
AVAILABLE_HOSTSconst AVAILABLE_HOSTS = [ SERVER_IP, '127.0.0.1' ];
An array of IP addresses that are allowed to access routes protected by the api_example and cron_example middleware (or any middleware that checks against this list). Requests from any other IP will receive a 403 Forbidden JSON response.
Typically includes SERVER_IP and 127.0.0.1 for local calls. Add any trusted internal IPs for inter-service communication.
ENTITY_DIRECTORYconst ENTITY_DIRECTORY = __DIR__ . '/../App/Entity';
Absolute path to the directory containing your Doctrine entity classes. Used by the Translator during DEV_MODE to scan entities for TranslatablePropertyName attributes and auto-populate translation files.
LANGUAGES_LISTconst LANGUAGES_LIST = [ 'en' ];
An array of locale keys your application supports. The first entry is treated as the default locale when no session locale is set and the browser's Accept-Language header doesn't match anything in the list.
Locale keys must match constants in PHP_SF\System\Classes\Helpers\Locale. Examples:
const LANGUAGES_LIST = [ 'en' ]; // English only
const LANGUAGES_LIST = [ 'en', 'pl', 'uk' ]; // English, Polish, Ukrainian
Adding a new language here is the only step needed to enable it — the Translator will automatically create the corresponding locale file in lang/ on the next request in DEV_MODE.
These have sensible defaults or are only needed for specific features.
DEV_MODE note on APP_ENVDEV_MODE and Symfony's APP_ENV are independent. You can run APP_ENV=prod with DEV_MODE=true (useful for debugging production config locally) or APP_ENV=dev with DEV_MODE=false (useful for testing production cache behaviour). They control different things and do not need to match.
This is the config/constants.example.php with all constants filled in for a typical development setup:
<?php declare( strict_types=1 );
use PHP_SF\System\Classes\Helpers\Locale;
use PHP_SF\System\Classes\Helpers\TimeZone;
const DEV_MODE = true;
const TEMPLATES_CACHE_ENABLED = false;
const DEFAULT_TIMEZONE = TimeZone::ETC_UTC;
const SERVER_IP = '127.0.0.1';
const APPLICATION_NAME = 'My Application';
const AVAILABLE_HOSTS = [ SERVER_IP, '127.0.0.1' ];
const ENTITY_DIRECTORY = __DIR__ . '/../App/Entity';
const LANGUAGES_LIST = [ 'en' ];
And for a typical production setup:
<?php declare( strict_types=1 );
use PHP_SF\System\Classes\Helpers\TimeZone;
const DEV_MODE = false;
const TEMPLATES_CACHE_ENABLED = true;
const DEFAULT_TIMEZONE = TimeZone::ETC_UTC;
const SERVER_IP = '10.0.0.1'; // your actual server IP
const APPLICATION_NAME = 'My Application';
const AVAILABLE_HOSTS = [ SERVER_IP, '127.0.0.1' ];
const ENTITY_DIRECTORY = __DIR__ . '/../App/Entity';
const LANGUAGES_LIST = [ 'en' ];
Constants are loaded very early in the boot sequence — before the framework kernel, before Composer's autoloader in some contexts, and before any Symfony bundle. The load order in public/index.php is:
vendor/autoload.php
functions/functions.php
config/constants.php ← here
config/eventListeners.php
.env (via Dotenv)
PHP_SF\System\Kernel boot
This means constants are available everywhere in the application without any injection or container lookup, and it also means they cannot reference any class that isn't available before autoloading — which is why TimeZone and Locale are simple constant-holding classes with no dependencies.
Forgetting to copy the example file — the file is in .gitignore and won't exist in a fresh clone. The installer handles this, but manual setup requires the cp step.
Setting DEV_MODE = true in production — routes won't cache, translations will be scanned on every request, and APCu will be wiped on boot. Performance will be significantly degraded.
Wrong LANGUAGES_LIST locale keys — locale keys must exactly match constants defined in Locale class (e.g. 'en', 'pl', 'uk'). An invalid key won't throw immediately but will cause translation lookups to fail silently.
SERVER_IP mismatch — if SERVER_IP doesn't match the actual server IP, routes protected by api_example or cron_example middleware (or any middleware checking AVAILABLE_HOSTS) will return 403 for all callers including the server itself.