This page covers getting a new PHP-SF project running from scratch, either using the interactive scripts or manually.
Before starting, make sure you have the following installed:
| Requirement | Minimum version | Notes |
|---|---|---|
| PHP | 8.3 | With extensions: apcu, amqp, curl, gd, intl, memcached, redis, yaml, opcache |
| Composer | 2.x | |
| Node.js + yarn | Node 18+ | For frontend assets |
| Redis | Any recent | Required — used for routing cache and app cache |
| PostgreSQL | 15+ | Primary supported database |
| Symfony CLI | Any recent | Optional but recommended for local dev |
| Docker | Any recent | Optional — docker-compose.yml provided for all services |
The recommended way is composer create-project — it bootstraps the project and runs composer install in one step:
composer create-project nations-original/php-simple-framework-template my-project
cd my-project
Alternatively, clone directly from GitHub:
git clone https://github.com/Ondottr/PHP_SF_template my-project
cd my-project
composer install
The framework itself (nations-original/php-simple-framework) is a Composer dependency and will be installed automatically either way.
The project ships with two installer scripts with distinct responsibilities:
| Script | When to use |
|---|---|
init.sh |
First time only — setting up a brand-new project from the template |
install.sh |
Every subsequent machine — installing a project that is already configured |
Run init.sh once per project. After that, every developer who clones the repo uses install.sh.
Run this when you have just cloned the template and nothing is configured yet:
chmod +x init.sh && ./init.sh
init.sh performs the full project initialization in order:
1. Composer dependencies
Runs composer install if vendor/ doesn't exist (required early because update_doctrine_yaml needs vendor/autoload.php).
2. Database connections
Prompts you to add one or more database connections. For each connection you provide:
main, blog, catalog)postgresql, mysql, or mariadb)For each connection the script:
DATABASE_<EM>_* variables into .env and .env.exampleconfig/packages/doctrine.yamlApp/Entity/<Pascal>/ and App/Repository/<Pascal>/ directoriesApp/Maker/Make<Pascal>Entity.php (console command: <em>:make:entity)3. User entity
The framework requires a User entity for authentication, session handling, and access control. init.sh generates a ready-to-use User entity and UserRepository in the chosen entity manager's directory, then wires ->setApplicationUserClassName(User::class) into bin/console, public/index.php, and tests/bootstrap.php.
4. Environment configuration
Prompts for:
APP_ENV (dev, test, or prod) and APP_DEBUGSERVER_PREFIX — namespaces cache keys; important when running multiple environments on the same Redis instance5. config/constants.php
Copies config/constants.example.php → config/constants.php, then prompts for:
SERVER_IP — added to AVAILABLE_HOSTSTEMPLATES_CACHE_ENABLED — enables compiled template caching in RedisDEV_MODE — enables APCu clearing on boot and disables route cachingAPPLICATION_NAME6. Node dependencies and assets
Runs yarn install and yarn build for both the main project and public/CKEditor/ if node_modules/ doesn't exist.
7. Codeception actors
Runs vendor/bin/codecept build to generate actor classes.
At the end the script offers to delete itself — since it is intended to run only once per project.
If the project is already configured and you run init.sh again, it detects the existing connections and offers to add a new one without touching your existing configuration.
Use this when cloning a project that already has doctrine.yaml and entity directories committed:
chmod +x install.sh && ./install.sh
install.sh sets up a machine for an already-initialized project:
1. .env file (only when .env doesn't exist yet)
Copies .env.example → .env, then prompts for credentials for every DATABASE_*_USER line that is still commented out:
doctrine.yaml)APP_ENV and APP_DEBUGSERVER_PREFIX2. config/constants.php (only when the file is missing or constants are commented out)
Copies config/constants.example.php → config/constants.php if it doesn't exist, then prompts for SERVER_IP, TEMPLATES_CACHE_ENABLED, DEV_MODE, and APPLICATION_NAME for any that are still commented.
3. Composer dependencies
Runs composer install if vendor/ doesn't exist.
4. Node dependencies and assets
Runs yarn install and yarn build if node_modules/ doesn't exist.
5. Codeception actors
Runs vendor/bin/codecept build.
6. Database
Detects configured entity managers from .env, then prompts:
doctrine:database:create + doctrine:schema:drop -f + doctrine:schema:create per EM)doctrine:fixtures:load per EM)Both scripts make run.sh executable. After installation completes:
./run.sh
This starts the dev server on port 7000. Options:
symfony is availablephp -S 127.0.0.1:7000 -t public) otherwise./run.sh 8080If you prefer to configure things yourself:
Step 1 — Copy config files
cp .env.example .env
cp config/constants.example.php config/constants.php
Step 2 — Edit .env
At minimum you need (repeat the DATABASE_* block for each entity manager configured in doctrine.yaml):
APP_ENV=dev
APP_DEBUG=true
DATABASE_MAIN_HOST=127.0.0.1
DATABASE_MAIN_PORT=5432
DATABASE_MAIN_USER=dbuser
DATABASE_MAIN_PASSWORD=dbpass
DATABASE_MAIN_DBNAME=my_database
DATABASE_MAIN_VERSION=16.0.0
# Optional — defaults to DATABASE_MAIN_DBNAME + _test if omitted
# DATABASE_MAIN_DBNAME_TEST=my_database_test
REDIS_CACHE_URL=redis://localhost:6379/0
MEMCACHED_SERVER=localhost
MEMCACHED_PORT=11211
SERVER_PREFIX=your-app-name
ADMIN_EMAIL=admin@example.com
ADMIN_PASSWORD=your_admin_password
The driver is hardcoded in config/packages/doctrine.yaml (set during init.sh) and does not belong in .env.
Step 3 — Edit config/constants.php
At minimum you need:
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 = 'Your App Name';
const AVAILABLE_HOSTS = [ SERVER_IP, '127.0.0.1' ];
const ENTITY_DIRECTORY = __DIR__ . '/../App/Entity';
const LANGUAGES_LIST = [ 'en' ];
See Constants & Configuration for a full reference of every constant.
Step 4 — Install dependencies
composer install
yarn install && yarn build
Step 5 — Database
php bin/console doctrine:database:create --if-not-exists --em=main
php bin/console doctrine:schema:create --em=main
php bin/console doctrine:fixtures:load --no-interaction --em=main
Step 6 — Run
./run.sh
# or
php -S 127.0.0.1:7000 -t public
If you'd rather not install Redis, PostgreSQL, Memcached, and RabbitMQ locally, the project includes a docker-compose.yml with all services pre-configured:
docker-compose up -d
This starts:
| Service | Container port | Host port |
|---|---|---|
| Memcached | 11211 | 7001 |
| Redis | 6379 | 7002 |
| PostgreSQL | 5432 | 7003 |
| RabbitMQ | 5672 | 7004 |
| MySQL | 3306 | 7005 |
| MariaDB | 3306 | 7006 |
| Selenium | 4444 | 4444 |
With Docker running, your .env would be:
DATABASE_MAIN_HOST=127.0.0.1
DATABASE_MAIN_PORT=7003
DATABASE_MAIN_USER=dbuser
DATABASE_MAIN_PASSWORD=dbpass
DATABASE_MAIN_DBNAME=my_database
DATABASE_MAIN_VERSION=16.0.0
# DATABASE_MAIN_DBNAME_TEST=my_database_test # optional, defaults to DBNAME + _test
REDIS_CACHE_URL=redis://127.0.0.1:7002/0
MEMCACHED_SERVER=127.0.0.1
MEMCACHED_PORT=7001
MESSENGER_TRANSPORT_DSN=amqp://admin:admin@127.0.0.1:7004/%2f
See Docker & Local Environment for a full breakdown of the Docker configuration.
Once running, open https://127.0.0.1:7000 (or http:// if not using Symfony CLI). You should see the PHP-SF welcome page showing the framework version and project directory path.
If you see a Symfony error instead, check:
config/constants.php exists and DEV_MODE is definedREDIS_CACHE_URL is correct — the framework will fail silently on cache misses if Redis is unreachableDuring development, if routes or templates aren't updating:
# Clear all application cache (Redis, APCu, Memcached, session)
php bin/console app:cache:clear
# Clear Symfony cache
php bin/console symfony:cache:clear
Or hit the API endpoint directly if the server is running:
GET /api/cache_clear/all
Note: app:cache:clear only works from hosts listed in AVAILABLE_HOSTS.