phastasf / framework
A lightweight PHP framework for building CLI, web and API applications
Installs: 42
Dependents: 1
Suggesters: 0
Security: 0
Stars: 2
Watchers: 0
Forks: 0
Open Issues: 0
pkg:composer/phastasf/framework
Requires
- php: ^8.2
- middlewares/client-ip: ^2.1
- vaibhavpandeyvpz/ank: ^2.0
- vaibhavpandeyvpz/clip: ^1.0
- vaibhavpandeyvpz/dakiya: ^3.0
- vaibhavpandeyvpz/databoss: ^2.1
- vaibhavpandeyvpz/datum: ^1.1
- vaibhavpandeyvpz/drishti: ^1.1
- vaibhavpandeyvpz/envelope: ^1.0
- vaibhavpandeyvpz/filtr: ^2.0
- vaibhavpandeyvpz/godam: ^2.0
- vaibhavpandeyvpz/jweety: ^2.0
- vaibhavpandeyvpz/katora: ^2.0
- vaibhavpandeyvpz/kram: ^1.0
- vaibhavpandeyvpz/kunfig: ^2.0
- vaibhavpandeyvpz/phew: ^2.0
- vaibhavpandeyvpz/phlash: ^3.0
- vaibhavpandeyvpz/qatar: ^1.0
- vaibhavpandeyvpz/samay: ^1.0
- vaibhavpandeyvpz/sandesh: ^3.0
- vaibhavpandeyvpz/soochak: ^2.0
- vaibhavpandeyvpz/tez: ^3.0
- vaibhavpandeyvpz/vidyut: ^3.0
Requires (Dev)
- vaibhavpandeyvpz/prayog: ^1.0
README
A lightweight, modern PHP framework for building CLI, web, and API applications. Built on PSR standards with a clean, intuitive API.
Features
- PSR Standards: PSR-7, PSR-11, PSR-15, PSR-3, PSR-6, PSR-16, PSR-20
- Dependency Injection: Automatic dependency resolution
- Routing & Middleware: Fast routing with PSR-15 middleware pipeline
- Database & ORM: Multi-database support (MySQL, PostgreSQL, SQLite, SQL Server) with Datum ORM
- Migrations: Schema versioning with Kram
- Views: Template engine with layout inheritance
- Authentication: JWT-based authentication
- Queue System: Job queues with Redis and ElasticMQ/SQS
- Caching: Multiple backends (File, Memory, Redis, Predis, Memcache)
- Logging: Flexible logging with multiple backends
- Email: SMTP, Mailgun, and Resend transports
- Validation: Powerful input validation
- Console Commands: Built-in CLI commands and generators
Requirements
- PHP 8.2+
- Composer
Installation
composer require phastasf/framework
Quick Start
Web Application
Create public/index.php:
<?php require __DIR__.'/../vendor/autoload.php'; define('BASE_PATH', __DIR__.'/..'); $framework = new Phast\Framework; $framework->getWebEntrypoint()->handle();
Console Application
Create console:
#!/usr/bin/env php <?php require __DIR__.'/vendor/autoload.php'; define('BASE_PATH', __DIR__); $framework = new Phast\Framework; exit($framework->getConsoleEntrypoint()->run());
chmod +x console
Configuration
Configuration files are in config/. The framework loads defaults from the package and merges your project's config/ overrides.
Application
// config/app.php return [ 'debug' => env('APP_DEBUG', false), 'controllers' => ['namespace' => 'App\\Controllers'], 'models' => ['namespace' => 'App\\Models'], 'jobs' => ['namespace' => 'App\\Jobs'], ];
Database
// config/database.php return [ 'driver' => env('DB_DRIVER', 'mysql'), 'migrations' => BASE_PATH.'/database/migrations', 'mysql' => [ 'host' => env('DB_HOST', 'localhost'), 'database' => env('DB_DATABASE', ''), 'username' => env('DB_USERNAME', 'root'), 'password' => env('DB_PASSWORD', ''), ], ];
Session
Configure session cookie settings:
// config/session.php return [ 'cookie' => [ 'name' => env('SESSION_COOKIE', 'PHPSESSID'), 'lifetime' => (int) env('SESSION_LIFETIME', 7200), 'path' => env('SESSION_PATH', '/'), 'domain' => env('SESSION_DOMAIN', null), 'secure' => env('SESSION_SECURE', false), 'httponly' => env('SESSION_HTTPONLY', true), 'samesite' => env('SESSION_SAMESITE', 'Lax'), // 'Strict', 'Lax', or 'None' ], ];
Trusted Proxies
When running behind a reverse proxy or load balancer, configure trusted proxies for accurate client IP detection:
// config/proxies.php return [ 'trusted' => [ '10.0.0.0/8', // Private network '172.16.0.0/12', // Docker network '192.168.0.0/16', // Private network '127.0.0.1', // Localhost IPv4 '::1', // Localhost IPv6 // Add your production proxy IPs here // '203.0.113.0/24', // Your load balancer IP range ], 'headers' => [ 'Forwarded', 'X-Forwarded-For', 'X-Real-Ip', 'Client-Ip', ], ];
Routing
// routes/web.php return function (Router $router) { $router->get('/', 'HomeController@index'); $router->get('/users/{id}', 'UserController@show'); $router->post('/users', 'UserController@store'); };
Middleware
Middleware is configured in config/middleware.php:
// config/middleware.php return [ // Core framework middleware (required) \Phast\Middleware\ErrorHandlerMiddleware::class, \Phast\Middleware\SessionMiddleware::class, // CORS middleware (should be early in pipeline to handle preflight requests) \Phast\Middleware\CorsMiddleware::class, // Client IP detection middleware (must be before routing if behind proxy) // \Phast\Middleware\ClientIpMiddleware::class, // Add AuthMiddleware here if you want authentication // \Phast\Middleware\AuthMiddleware::class, // Add your custom middleware here (before routing) \App\Middleware\CustomMiddleware::class, \Phast\Middleware\RoutingMiddleware::class, \Phast\Middleware\DispatcherMiddleware::class, ];
Generate a new middleware:
php console g:middleware CustomMiddleware
Client IP Detection
When running behind a reverse proxy or load balancer, add ClientIpMiddleware to your middleware stack to correctly detect client IP addresses. The middleware reads trusted proxy configuration from config/proxies.php and extracts the real client IP from proxy headers.
CORS (Cross-Origin Resource Sharing)
Add CorsMiddleware to your middleware stack to handle cross-origin requests. The middleware automatically handles preflight OPTIONS requests and adds appropriate CORS headers to responses.
The middleware is configured via config/cors.php:
// config/cors.php return [ // Allowed origins ('*' for all, or array of specific origins) // Note: Cannot use '*' when allow_credentials is true 'allowed_origins' => env('CORS_ALLOWED_ORIGINS', '*'), // Allowed HTTP methods 'allowed_methods' => [ 'GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'OPTIONS', ], // Allowed request headers ('*' for all, or array of specific headers) 'allowed_headers' => env('CORS_ALLOWED_HEADERS', '*'), // Headers that can be exposed to the client 'exposed_headers' => [], // Maximum age (in seconds) for preflight request cache 'max_age' => (int) env('CORS_MAX_AGE', 86400), // Allow credentials (cookies, authorization headers, etc.) // Note: When true, allowed_origins cannot be '*' 'allow_credentials' => (bool) env('CORS_ALLOW_CREDENTIALS', false), // Paths/prefixes to include (empty = all paths) 'include' => [], // Paths/prefixes to exclude 'exclude' => [], ];
Configuration Examples
Allow all origins (development):
'allowed_origins' => '*', 'allow_credentials' => false,
Allow specific origins (production):
'allowed_origins' => [ 'https://example.com', 'https://www.example.com', ], 'allow_credentials' => true,
Apply CORS only to API routes:
'include' => ['/api'], 'exclude' => [],
Exclude certain paths from CORS:
'include' => [], 'exclude' => ['/admin', '/internal'],
Important Notes
- When
allow_credentialsistrue,allowed_originscannot be'*'(must specify exact origins) - The middleware automatically handles preflight OPTIONS requests
- Path matching uses prefix-based matching (paths starting with the pattern)
- CORS headers are only added when the request includes an
Originheader
Service Providers
Service providers are configured in config/providers.php:
// config/providers.php return [ // ConfigProvider must be first (other providers depend on it) \Phast\Providers\ConfigProvider::class, \Phast\Providers\CacheProvider::class, \Phast\Providers\DatabaseProvider::class, // ... other framework providers // Add your custom providers here \App\Providers\CustomProvider::class, ];
Generate a new service provider:
php console g:provider CustomProvider
Service providers implement Phast\Providers\ProviderInterface with two methods:
provide(Container $container): Register services in the containerinit(Container $container): Initialize services after all providers are registered
namespace App\Providers; use Katora\Container; use Phast\Providers\ProviderInterface; class CustomProvider implements ProviderInterface { public function provide(Container $container): void { // Register services here $container->set('custom.service', fn() => new CustomService); } public function init(Container $container): void { // Initialize services here (called after all providers are registered) $service = $container->get('custom.service'); $service->initialize(); } }
Controllers
namespace App\Controllers; use Phast\Controller; class HomeController extends Controller { public function index(ServerRequestInterface $request): ResponseInterface { return $this->render('welcome', ['message' => 'Hello, Phast!']); } }
Models
namespace App\Models; use Datum\Model; class User extends Model { protected static ?string $table = 'users'; } // Usage $user = User::find(1); $user = new User; $user->name = 'John'; $user->save();
Migrations
// Generated migration class CreateUsersTable implements MigrationInterface { public function up(ConnectionInterface $connection): void { $connection->execute("CREATE TABLE users (...)"); } public function down(ConnectionInterface $connection): void { $connection->execute("DROP TABLE users"); } }
Seeders
Seeders add fake or test data to the database. You can insert data via the connection (raw) or using models. Dependencies (e.g. ConnectionInterface) are injected via the seeder constructor and resolved by the container. Only the seeders listed in config database.seed are run when you execute the seed command.
// Generated seeder (implements Phast\Database\SeederInterface) // Dependencies are injected via constructor and resolved by the container. use Databoss\ConnectionInterface; use Phast\Database\SeederInterface; class UserSeeder implements SeederInterface { public function __construct( private readonly ConnectionInterface $connection ) {} public function run(): void { // Raw connection $this->connection->insert('users', ['name' => 'John', 'email' => 'john@example.com']); // Or via model $user = new \App\Models\User; $user->name = 'Jane'; $user->email = 'jane@example.com'; $user->save(); } }
Configure which seeders run in config/database.php:
'seed' => [ 'DatabaseSeeder', 'UserSeeder', ],
Queue Jobs
namespace App\Jobs; use Qatar\Job; class SendEmailJob extends Job { public function handle(array $payload): void { // Job logic } public function retries(): int { return 3; } }
Console Commands
Generators
g:command- Generate console commandg:controller- Generate controllerg:event- Generate event classg:job- Generate jobg:middleware- Generate middleware classg:migration- Generate migrationg:model- Generate modelg:provider- Generate service providerg:seeder- Generate seeder class
Database
m:up- Run pending migrationsm:down [count]- Rollback migrations (default: 1)seed- Run database seeders (only those in configdatabase.seed)
Development
serve- Start development serverworker- Run queue workershell- Start interactive PHP shell (REPL) with container accessuncache- Clear cached config, routes, and application cache
Usage Examples
Caching
$cache = $container->get(CacheInterface::class); $cache->set('key', 'value', 3600); $value = $cache->get('key');
Logging
$logger = $container->get(LoggerInterface::class); $logger->info('User logged in', ['user_id' => 123]);
HTTP Client
The framework includes a PSR-18 compliant HTTP client:
use Psr\Http\Client\ClientInterface; $client = $container->get(ClientInterface::class); $request = $requestFactory->createRequest('GET', 'https://api.example.com/data'); $response = $client->sendRequest($request);
Validation
use Filtr\Validator; $validator = new Validator; $validator->required('email')->email(); $validator->required('password')->min(8); $result = $validator->validate($data);
JWT Authentication
// config/auth.php return [ 'jwt' => [ 'secret' => env('JWT_SECRET'), 'algorithm' => 'HS256', ], 'middleware' => [ 'include' => ['/api/*'], 'exclude' => ['/api/auth/*'], 'required' => true, ], ];
Error Handling
The framework includes centralized error handling that:
- Catches all exceptions
- Returns JSON for API requests (
Accept: application/json) - Renders HTML error pages for web requests
- Logs 5xx errors automatically
- Shows debug info when
app.debugis enabled
License
MIT License - see LICENSE file.
Credits
Built on excellent PSR-compliant libraries:
- Katora - DI Container
- Kunfig - Configuration Management
- Databoss - Database Connections
- Datum - ORM
- Kram - Migrations
- Tez - Routing
- Vidyut - Middleware Pipeline
- Sandesh - HTTP Messages
- Phew - Templates
- Filtr - Validation
- Drishti - Logging
- Godam - Caching
- Qatar - Queues
- Jweety - JWT
- Envelope - Email
- Phlash - Flash Messages
- Ank - Captcha
- Soochak - Events
- Samay - Clock
- Dakiya - HTTP Client (PSR-18)
- Clip - CLI Commands
- Prayog - REPL/Shell (dev)