πΊπΈ English | πͺπΈ EspaΓ±ol
Parina is a minimal micro-framework for modern PHP applications. It provides just enough structure to build applications with clarity, control, and peak performance, adhering to Feature-Driven Architecture and clean design patterns.
- DI Container with Reflection: Automatic resolution and constructor injection of dependencies for Handlers and Middlewares.
- Feature-Driven Architecture: Handlers, views, and tests organized by cohesive business features (e.g.
Authentication,UserManagement,Marketing) instead of role-based folders or separate technical layers. - Stateless HTTP Request (
Request): Unified payload input (input()), simple HTTP header fetching (header()), and local request context attributes (setAttribute()) for clean middleware-to-handler data sharing. - CQS & Adapter Patterns: Separation of read queries and write commands inside Repositories (validated automatically by the system Linter), coupled with dynamic database driver adapters (SQLite, MySQL, PostgreSQL) adhering to the Open/Closed Principle. See CQS Recommendations for detailed rules.
- XSS Protection: Secure variable escaping inside templates using the global helper function
h().
Clarity over abstraction. Control over convenience.
Parina focuses on:
- Explicit design: No magic, no hidden lifecycles.
- Minimal overhead: Every byte and millisecond counts.
- Predictable flow: What you see is exactly what executes.
- A request enters through a front controller.
- It goes through the middleware pipeline.
- Middleware can block or pass.
- It reaches the registered handler.
- Handler executes core logic.
- Returns a standard response.
- No heavy magic.
- No hidden framework lifecycles.
- No unnecessary abstractions.
- Just clear, linear execution.
[ Request ] βββ> [ Middleware Pipeline ] βββ> [ Handler ]
β β
β (Returns Response) β (Returns Response)
βΌ βΌ
[ Response ] <βββββββββββββββββ
Each middleware layer follows a simple binary rule:
- Returns
Responseβ Stop execution and emit response. - Returns
nullβ Continue to the next layer.
namespace Parina\Shared\Middlewares;
use Parina\Core\Interfaces\RequestInterface;
use Parina\Core\Interfaces\Middleware;
use Parina\Core\Interfaces\Response;
use Parina\Core\Responses\ErrorResponse;
class SimpleAuth implements Middleware
{
public function handle(RequestInterface $request): ?Response
{
if (!isset($_SESSION['user'])) {
return new ErrorResponse("Unauthorized", 401);
}
return null; // Move to the next layer
}
}Security is first-class and lives exactly where it belongs: in the middleware pipeline.
- Rate limiting
- Request size validation
- CSRF protection
- Same-origin policy (CORS)
- Authentication (Basic / JWT)
- Authorization (ACL)
Designed for minimal overhead and microsecond-accuracy:
- ~0.0007 seconds per request execution.
- ~0.05 MB RAM footprint.
- Fully Opcache friendly.
// public/index.php
use Parina\Core\Router;
use Parina\Core\Kernel;
use Parina\Core\Container;
use Parina\Core\Config;
use Parina\Shared\Infrastructure\Db;
require_once __DIR__ . '/../src/autoload.php';
// Instantiate DI container & load dynamic dependencies
$container = new Container();
if (file_exists(__DIR__ . '/../config/dependencies.php')) {
$container->load(require __DIR__ . '/../config/dependencies.php');
}
// Initialize database with dynamically resolved adapter (OCP)
Db::setConfig(Config::getDbConfig());
Db::init($container->get(\Parina\Shared\Infrastructure\DatabaseAdapter::class));
$router = new Router();
$routes = require '../config/routes.php';
foreach ($routes as $route) {
$router->add($route['method'], $route['path'], $route['handler'], $route['middleware'] ?? []);
}
$request = \Parina\Core\Request::capture();
$kernel = new Kernel($router, $container);
$response = $kernel->handle($request);
$emitter = new \Parina\Core\ResponseEmitter();
$emitter->emit($response);namespace Parina\Features\UserManagement\Handlers;
use Parina\Core\Interfaces\Handler;
use Parina\Core\Interfaces\Response;
use Parina\Core\Interfaces\RequestInterface;
use Parina\Core\Responses\HtmlResponse;
use Parina\Core\View;
use Parina\Features\UserManagement\Queries\UserQueryRepositoryInterface;
class UsersListHandler implements Handler
{
// Resolved and injected automatically by the DI Container via Reflection
public function __construct(private UserQueryRepositoryInterface $userRepo) {}
public function handle(RequestInterface $request): Response
{
$users = $this->userRepo->all();
// Secure HTML output using the global h() helper to prevent XSS
$content = View::renderWithLayout("UserManagement/Views/list", "default", ['users' => $users]);
return new HtmlResponse($content, 200);
}
}<!-- Features/UserManagement/Views/list.php -->
<h1>Users List</h1>
<ul>
<?php foreach ($users as $user): ?>
<li><?= h($user['username']) ?></li>
<?php endforeach; ?>
</ul>Parina includes a CLI tool to generate routing configurations, handler classes, and unit tests directly from a CSV file.
-
Define your routes in a CSV file (e.g.,
routes.csv):Method,Path,Feature,HandlerName,Middlewares,Description GET,/,Marketing,Home,,Home page GET,/about,Marketing,About,,About us
-
Run the scaffolding tool:
php bin/scaffold.php routes.csv
This will automatically generate:
- Route configurations in
config/routes.php. - Missing Handler classes in
src/Features/. - Basic unit tests in
tests/Features/to verify your handlers.
Parina is developed with PHPUnit, focusing on complete coverage.
tests/
βββ KernelTest.php
βββ RouterTest.php
βββ ContainerTest.php
βββ Features/
Most complexity in software is accidental. Parina asks:
What is the smallest structure that still works correctly, securely, and fast?
Parina is not minimal by limitation. It is minimal by intention. It removes everything you do not actually need.
For a detailed explanation of the core philosophy and how the entire framework fits in a paper napkin diagram, see THE-NAPKIN-REVOLUTION.md.
For directory layout, permissions, and production tips, see DEPLOY.md.
To remove all demo files and reset the framework to a fresh state, see CLEANUP.md.
For a detailed guide on generating commands, queries, scaffolding features, and managing active routes, see docs/tools.md.
To run the framework locally using PHP's built-in development server:
git clone https://github.com/nelsonrojasn/Parina-Framework.git
cd Parina-Framework
php -S localhost:8000 -t publicMIT License.

