This project is currently under active development.
Features may be incomplete or subject to change.
It is not recommended for production use.
Hard is a lightweight, object-oriented framework written in pure PHP. It focuses on simplicity, strict typing, and clean architecture principles (SOLID, KISS, DRY).
The goal of Hard? Peek behind the curtain of web frameworks, pull them apart, and see if I can make the magic happen myself.
- Strict typing across the entire codebase
- Simple
Router
with support forGET
,POST
,PUT
,PATCH
,DELETE
- Robust error handling for
404 Not Found
and405 Method Not Allowed
- Dynamic URL parameters (e.g.,
/users/{id}
) - Effortless Redirects
- Request and Response abstractions
- Contracts for request handlers
- Simple file-based logging
- Middleware
- Validation
- And more ...
hard/
├── app/
│ ├── Handlers/ # Your request handlers
│ └── Routes/ # Route definitions (web.php, api.php)
├── infra/
│ ├── Contracts/ # Interfaces and contracts
│ ├── Enums/ # HTTP method enum
│ ├── Exceptions/ # Custom exceptions (NotFound, MethodNotAllowed)
│ └── Http/ # Core HTTP classes
│ └── Handlers/ # Core handlers (NotFound, Redirect, MethodNotAllowed)
├── public/
│ └── index.php # Front controller
├── storage/
│ └── logs/ # Log files
├── tests/ # Test suite
└── vendor/ # Composer dependencies
Clone the repository:
git clone https://github.com/clebsonsh/hard-framework.git
cd hard
composer install
Run a development server:
composer dev
Visit 👉 http://localhost:8000
Inside app/Routes/web.php
:
use App\Handlers\AboutHandler;
use App\Handlers\HomeHandler;
use Infra\Http\Router;
return function (Router $router) {
// The handler is a class string, it will be lazy-loaded.
$router->get('/', HomeHandler::class);
// The handler is an instance, it is loaded immediately.
$router->get('/about', new AboutHandler);
};
You can define dynamic segments in your routes by wrapping a parameter name in curly braces {}
. The router will
automatically extract the value from the URL.
use App\Handlers\UserHandler;
use Infra\Http\Router;
return function (Router $router) {
// This route will match URLs like /users/42 or /users/clebson
$router->get('/users/{id}', new UserHandler);
};
Easily create redirects with a specific HTTP status code.
use Infra\Http\Router;
return function (Router $router) {
// Redirects /old-url to /new-url with a 301 status code
$router->redirect('/old-url', '/new-url', 301);
};
All handlers implement RequestHandlerInterface
. You can access route parameters from the Request
object.
namespace App\Handlers;
use Infra\Http\Request;
use Infra\Http\Response;
use Infra\Interfaces\RequestHandlerInterface;
class UserHandler implements RequestHandlerInterface
{
public function handle(Request $request): Response
{
// Retrieve the 'id' parameter from the URL
$userId = $request->getParam('id');
return new Response::html("<p>Showing user: {$userId}<p>");
}
}
The framework provides a simple file-based logging system. You can use the following helper functions to write messages to the log file:
info(string $message)
debug(string $message)
warn(string $message)
error(string $message)
Logs are stored in the storage/logs
directory, with a new file created each day.
Example:
// in any part of your application
info('This is an informational message.');
try {
// some operation that might fail
} catch (Exception $e) {
error((string) $e);
}
- Define a handler in
app/Handlers
- Register it in a route file (
web.php
orapi.php
) - Run the server and visit the route
This project uses Pest for testing. The test suite provides 100% unit test coverage for the core
framework components in the infra/
directory.
To run the entire test suite, use the following Composer script:
composer test
This will execute all tests located in the tests/
directory.
This project uses PHPStan for static analysis to find bugs before they reach production.
To run PHPStan, use the following Composer script:
composer lint
This will analyze the app/
,infra/
and public/
directories.
Pull requests are welcome! Please open an issue first to discuss what you’d like to change.
MIT License – free to use, modify, and distribute.