donchev / framework
A Tiny PHP Framework
Installs: 23
Dependents: 0
Suggesters: 0
Security: 0
Stars: 2
Watchers: 1
Forks: 0
Open Issues: 0
Type:package
Requires
- php: >=8.2
- ext-json: *
- doctrine/annotations: ^2.0
- donchev/simple-logger: ^2.1
- laminas/laminas-diactoros: ^3.5
- nette/mail: ^4.0
- nikic/fast-route: ^1.3
- php-di/php-di: ^7.0
- psr/http-message: ^2.0
- sergeytsalkov/meekrodb: ^3.1
- symfony/cache: ^7.2
- symfony/console: ^7.2
- symfony/yaml: ^7.2
- twig/twig: ^3.20
Requires (Dev)
- filp/whoops: ^2.18
- friendsofphp/php-cs-fixer: ^3.75
- phpunit/phpunit: ^12.1
README
A lightweight and expressive PHP framework built for clarity, structure, and extensibility. Ideal for small to mid-sized web applications.
Features
Built-in functionalities
- Dependency Injection Container (PHP-DI)
- Routing (FastRoute)
- Middleware support
- Templating with Twig
- Flash messages
- Database support via MeekroDB
- SMTP mailer (Nette Mail)
- Console commands (Symfony Console)
- Caching (Symfony Cache)
- Logging (donchev/simple-logger)
- Data validation and sanitization
Includes Bootstrap 5 and Bootstrap Icons for UI development.
Requirements
- PHP 8.2 or higher
Installation
You can install the framework using Composer.
composer create-project donchev/framework myapp
Configuration
All application configuration is located in config/settings.yaml
. Example:
app: env: dev name: Tiny Framework base_url: https://framework.test use_sessions: true log_file: '%var_dir%/log/framework.log' api: username: password: middleware: dir: '%base_dir%/src/Middleware' namespace: Donchev\Framework\Middleware db: host: name: username: password: port: 3306 charset: utf8mb4 mail: host: smtp.mailtrap.io username: password: secure: null port: 2525 from_name: 'Tiny Framework Mailer' from_email:
Override values via settings.local.yaml
.
Usage
Routing
Define routes in config/routes.php
:
return static function (RouteCollector $router) { $router->get('/', [HomeController::class, 'index']); $router->post('/submit', [ContactController::class, 'submit']); $router->get('/blog/{slug}', [BlogController::class, 'show']); };
Controllers
Controllers extend AbstractController
:
class HomeController extends AbstractController { public function index(): void { $this->renderTemplate('home/index.html.twig', [ 'title' => 'Welcome!' ]); } }
Sending Emails
use Nette\Mail\Message; $message = new Message(); $message->setFrom('you@site.com') ->addTo('user@example.com') ->setSubject('Hello') ->setBody('This is a test email.'); $mailer = $container->get(Mailer::class); $mailer->send($message);
Database (MeekroDB)
/** @var MeekroDB $db */ $db = $container->get(MeekroDB::class); $users = $db->query("SELECT * FROM users WHERE active = %i", 1);
Using Cache
use Symfony\Contracts\Cache\CacheInterface; $cache = $container->get(CacheInterface::class); $data = $cache->get('some_key', function () { return 'cached value'; });
Flash Messages
Set flash messages in controller:
$flash = new FlashService(); $flash->add('success', 'Saved successfully!');
Render them in Twig:
{% include '_flash.html.twig' with {'flashes': flashes} %}
Middleware
Implement MiddlewareInterface
and drop your class into src/Middleware
. It will be auto-loaded.
class RequestLoggerMiddleware implements MiddlewareInterface { public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface { // logging logic... return $handler->handle($request); } }
Twig Template Globals
Twig templates automatically have access to:
http_get
,http_post
,http_cookie
,http_session
settings
get_flash()
function
Data Validator & Sanitizer
Validator:
$validator = new DataValidator(); $data = [ 'name' => 'John Doe', 'age' => 32 ]; $rules = [ 'name' => 'string', 'age' => 'min:30' ]; $result = $validator->validate($data, $rules); // Output: [ 'age' => [ '"age" must have at least 30 characters' ] ]
Validator & Flash Messages:
class AuthController { public function login(Post $post, DataValidator $validator, FlashService $flashService): void { $data = [ 'email' => $post->get('email'), 'password' => $post->get('password'), ]; $rules = [ 'email' => 'required|email', 'password' => 'required|secure', ]; $errors = $validator->validate($data, $rules); if (!empty($errors)) { $flashService->addError($errors); // return or redirect with errors } //... } }
Sanitizer:
$sanitizer = new DataSanitizer(); $data = ['asd123', '1.5ds']; $sanitized = $sanitizer->sanitize($data, 'float'); // Output: [123.0, 1.5]
Console Commands
Define commands in bin/console
. Example:
class HelloCommand extends Command { protected string $signature = 'hello'; protected string $description = 'Says hello'; public function handle(): void { $this->info('Hello from the Tiny Framework!'); } }
Run them:
php bin/console hello
Code Style
This project uses php-cs-fixer. You can format your code using:
composer cs-fix
Check for issues without modifying files:
composer cs-check
Testing
The framework includes PHPUnit 12+ test coverage out of the box.
Run tests:
vendor/bin/phpunit
All test files are located in the tests/
folder and follow PSR-4 autoloading with the Tests\
namespace.
Development Mode
Set app.env: dev
to enable detailed error pages (via Whoops) and debugging tools.
Production
Set app.env: prod
to enable compiled container and cache.
License
This project is open-source and licensed under the MIT License.
Author
Developed by Donchev. Contributions are welcome.