A skeleton application for Phast Framework - a lightweight, modern PHP framework built on PSR standards.
This skeleton application provides a clean starting point for building applications with Phast Framework, including:
- âś… PSR Standards: Full compliance with PSR-7, PSR-11, PSR-15, PSR-3, PSR-6, PSR-16, and PSR-20
- âś… Routing: Example routes demonstrating controller actions and closures
- âś… Controllers: Base controller with helper methods for rendering views, JSON responses, and redirects
- âś… Views: Template rendering with Phew template engine
- âś… Console Commands: CLI entrypoint for running console commands
- âś… Error Handling: Centralized exception handling
- âś… Dependency Injection: Service container integration
- âś… Docker Support: Complete Docker setup with Traefik, MySQL, Redis, and development tools
- âś… Frontend Tooling: Vite + React setup with hot module replacement and production builds
- âś… Seeders: Generate and run seeders for development and testing data
- Docker and Docker Compose
- mkcert for local SSL certificates
- PHP 8.2 or higher (for local development without Docker)
- Node.js 22+ and Yarn (for frontend development)
Setup project:
# create new project
composer create-project phastasf/app my-app
# go into project dir
cd my-app
# create .env file
cp .env.example .envCreate SSL certificates:
mkcert local.dev '*.local.dev' localhost 127.0.0.1 ::1This will create certificate files (local.dev+4.pem and local.dev+4-key.pem) in the project root.
Add hostnames to /etc/hosts:
sudo nano /etc/hostsAdd the following lines:
127.0.0.1 web.local.dev
127.0.0.1 api.local.dev
127.0.0.1 phpmyadmin.local.dev
127.0.0.1 mailcatcher.local.dev
127.0.0.1 redis-insight.local.dev
Start services:
docker compose up -dOnce the Docker services are running, you can access:
- Frontend (Vite Dev Server): https://web.local.dev/
- Backend API: https://api.local.dev/
- Traefik Dashboard: http://localhost:8080
- phpMyAdmin: https://phpmyadmin.local.dev/
- MailCatcher: https://mailcatcher.local.dev/
- Redis Insight: https://redis-insight.local.dev/
GET /- Home page (renders welcome view)GET /health- Health check endpointGET /error- Error handling test routeGET /api/status- API status endpoint (example of route groups)
The Docker Compose setup includes:
- web - Node.js 22 container running Vite dev server for frontend development
- api - PHP 8.5 Apache container running the backend API
- worker - Queue worker container
- mysql - MySQL 8 database server
- redis - Redis 5 cache and queue backend
- traefik - Reverse proxy with automatic HTTPS
- phpmyadmin - Database management interface
- mailcatcher - Email testing tool
- redis-insight - Redis management interface
The project structure is as explained below:
phast-app/
├── app/
│ ├── Commands/ # Console commands
│ ├── Controllers/ # Application controllers
│ ├── Events/ # Event classes
│ ├── Jobs/ # Queue jobs
│ ├── Middleware/ # Custom middleware
│ ├── Models/ # Database models
│ └── Providers/ # Service providers
├── config/ # Configuration files (optional overrides)
├── database/
│ ├── migrations/ # Database migrations
│ └── seeders/ # Database seeders (development/testing)
├── .docker/ # Docker configuration files
│ └── vhost.conf # Apache virtual host configuration
├── public_html/ # Web server document root
│ ├── index.php # Web entrypoint
│ ├── .htaccess # Apache rewrite rules
│ ├── assets/ # Built frontend assets (JS, CSS, images)
│ └── index.html # Built HTML entry point (generated by Vite)
├── resources/
│ ├── assets/ # Frontend source files (Vite + React)
│ │ ├── App.tsx # Main React component
│ │ ├── App.css # Component styles
│ │ ├── index.html # HTML entry point
│ │ ├── index.css # Global styles
│ │ └── main.tsx # React entry point
│ └── views/ # View templates
├── routes/
│ └── web.php # Route definitions
├── storage/
│ ├── cache/ # Application cache
│ │ ├── app/ # Application-specific cache
│ │ ├── config.php # Cached configuration
│ │ └── routes.php # Cached routes
│ └── logs/ # Log files
├── console # CLI entrypoint
├── docker-compose.yml # Docker Compose configuration
├── Dockerfile # Multi-stage build (Node + PHP)
├── traefik.yml # Traefik configuration
├── vite.config.ts # Vite configuration
├── package.json # Node.js dependencies and scripts
├── tsconfig.json # TypeScript configuration
├── tsconfig.app.json # TypeScript config for app
├── tsconfig.node.json # TypeScript config for Node
├── eslint.config.js # ESLint configuration
├── composer.json # PHP dependencies
└── yarn.lock # Yarn lock file
Generate a new console command:
docker compose exec web php console g:command CreateUserGenerate a new controller:
docker compose exec web php console g:controller UserControllerGenerate a new model:
docker compose exec web php console g:model UserGenerate a new migration:
docker compose exec web php console g:migration create_users_tableGenerate a new job class:
docker compose exec web php console g:job SendEmailGenerate a new event class:
docker compose exec web php console g:event UserRegisteredGenerate a new middleware class:
docker compose exec web php console g:middleware CustomMiddlewareGenerate a new service provider:
docker compose exec web php console g:provider CustomServiceGenerate a new seeder class (for development/testing data):
docker compose exec web php console g:seeder UserSeederRun pending migrations:
docker compose exec web php console m:upRollback migrations (default: 1):
docker compose exec web php console m:downRollback multiple migrations:
docker compose exec web php console m:down 3Run database seeders (only those listed in config/database.php under seed):
docker compose exec web php console seedStart the development server:
docker compose exec web php console serveStart a queue worker:
docker compose exec worker php console workerStart an interactive PHP shell (REPL) with container access:
docker compose exec web php console shellClear cached config, routes, and application cache:
docker compose exec web php console uncacheConfiguration files can be placed in the config/ directory to override framework defaults. The framework loads default configurations from the package and merges your project-specific overrides.
Environment variables are configured in the .env file. The .env.example file includes default values configured for the Docker setup:
- Database connection uses
mysqlas hostname (Docker service name) - Redis connection uses
redisas hostname (Docker service name) - All services are accessible via
.local.devdomain with SSL certificates
Middleware allows you to intercept and modify HTTP requests and responses. Create a custom middleware using the generator:
docker compose exec web php console g:middleware CustomMiddlewareThis will create a middleware in app/Middleware/ that implements Psr\Http\Server\MiddlewareInterface.
The config/middleware.php file is automatically copied from the framework during composer install or composer update if it doesn't exist. This file defines the middleware pipeline that processes HTTP requests:
<?php
return [
// Core middleware (required for framework to work)
\Phast\Middleware\ErrorHandlerMiddleware::class,
\Phast\Middleware\SessionMiddleware::class,
// Client IP detection middleware (must be before routing)
\Phast\Middleware\ClientIpMiddleware::class,
// \Phast\Middleware\AuthMiddleware::class, // Uncomment to enable authentication
// Add your custom middleware here (before routing)
// \App\Middleware\CustomMiddleware::class,
\Phast\Middleware\RoutingMiddleware::class,
\Phast\Middleware\DispatcherMiddleware::class,
];Middleware is executed in the order defined in the array. Core middleware must remain in their positions for the framework to function correctly.
The ClientIpMiddleware correctly detects client IP addresses when running behind a reverse proxy (like Traefik). It reads trusted proxy configuration from config/proxies.php if it exists.
Service providers allow you to register services in the dependency injection container. Create a custom provider using the generator:
docker compose exec web php console g:provider CustomServiceThis will create a provider in app/Providers/ that implements Phast\Providers\ProviderInterface. The provider has two methods:
provide(Container $container)- Register services in the containerinit(Container $container)- Initialize services after all providers are registered
The config/providers.php file is automatically copied from the framework during composer install or composer update if it doesn't exist. You can customize it to add your own providers:
<?php
return [
// Framework providers (ConfigProvider must be first)
\Phast\Providers\ConfigProvider::class,
\Phast\Providers\CacheProvider::class,
// ... other framework providers ...
// Your custom providers
\App\Providers\CustomServiceProvider::class,
];Seeders add fake or test data to the database. They live in database/seeders/, implement Phast\Database\SeederInterface, and receive dependencies (e.g. ConnectionInterface) via constructor injection. Only the seeders listed in config/database.php under the seed key are run when you execute the seed command.
To run your seeders, add their class names (no namespace) to config/database.php:
'seed' => [
'DatabaseSeeder',
'UserSeeder',
],You can insert data via the raw connection or using models. Generate a new seeder with php console g:seeder SeederName.
The default database configuration in .env.example:
- Host:
mysql(Docker service name) - Database:
phastapp - Username:
phastapp - Password:
phastapp
MailCatcher is configured to catch all emails. Configure your .env to use SMTP:
MAIL_DRIVER=smtp
MAIL_HOST=mailcatcher
MAIL_PORT=1025Frontend environment variables are prefixed with VITE_ and are available via import.meta.env:
const apiBaseUrl = import.meta.env.VITE_API_BASE_URL || "/";Development: Set VITE_API_BASE_URL=https://api.local.dev in .env for separate API container.
Production: Leave unset (defaults to /) when PHP and frontend are served together by Apache.
The .env.example file includes:
# Frontend API Configuration
# Defaults to "/" (relative path) for production where PHP and frontend are served together
# Set to "https://api.local.dev" for development with separate API container
VITE_API_BASE_URL=https://api.local.devThis skeleton includes a modern frontend setup with Vite and React.
resources/assets/- Frontend source files (React components, styles, etc.)public_html/assets/- Built frontend assets (generated by Vite)public_html/index.html- Built HTML entry point (generated by Vite)
The frontend development server runs automatically in Docker via the web service. It provides:
- Hot Module Replacement (HMR) - Instant updates without page refresh
- Fast Refresh - React component state preservation during updates
- TypeScript Support - Full type checking and IntelliSense
- ESLint Integration - Code quality and style checking
The Vite dev server runs automatically in Docker. To run it locally:
yarn devBuild the frontend for production:
yarn buildThis compiles TypeScript, bundles assets, and outputs to public_html/.
Check code quality:
yarn lintThe frontend includes an example API connection test that calls /api/status. The API endpoint returns a simple 200 OK response to verify connectivity.
The Dockerfile includes a multi-stage build that:
- Builds the frontend using Node.js in a separate stage
- Copies the built assets to the PHP container
- Serves everything together via Apache
This ensures optimized production builds while keeping development fast with HMR.
View application logs:
docker compose logs -f webView worker logs:
docker compose logs -f workerRun any PHP command in the web container:
docker compose exec web php console <command>Access the container shell:
docker compose exec web bashStop all services:
docker compose downStop and remove volumes:
docker compose down -vFor complete documentation, visit the Phast Framework documentation.
Contributions are welcome! Please feel free to submit a Pull Request.
This project is open-sourced software licensed under the MIT license.
Built with Phast Framework.