Skip to content

Instantly share code, notes, and snippets.

@celsowm
Created November 19, 2024 21:37
Show Gist options
  • Save celsowm/f82d0c8216786fec23862ebe2bd7629d to your computer and use it in GitHub Desktop.
Save celsowm/f82d0c8216786fec23862ebe2bd7629d to your computer and use it in GitHub Desktop.
FastPHP v0.02
<?php
namespace FastPHP\Attributes;
#[\Attribute(\Attribute::TARGET_METHOD)]
class Route
{
public string $method;
public string $path;
public function __construct(string $method, string $path)
{
$this->method = strtoupper($method);
$this->path = $path;
}
}
<?php
namespace FastPHP;
use FastPHP\Attributes\Route;
class FastPHP
{
private array $routes = [];
public static function run(): void
{
$instance = new self();
$instance->autoRegisterControllers();
$instance->handleRequest();
}
private function autoRegisterControllers(): void
{
$classes = get_declared_classes();
foreach ($classes as $className) {
$reflection = new \ReflectionClass($className);
// Ignorar classes internas do PHP e do próprio FastPHP
if ($reflection->isInternal() || $reflection->getNamespaceName() === __NAMESPACE__) {
continue;
}
$methods = $reflection->getMethods(\ReflectionMethod::IS_PUBLIC);
foreach ($methods as $method) {
$attributes = $method->getAttributes(Route::class);
foreach ($attributes as $attribute) {
/** @var Route $route */
$route = $attribute->newInstance();
$this->addRoute($route->method, $route->path, [$reflection->newInstance(), $method->getName()]);
}
}
}
}
private function addRoute(string $method, string $path, callable $handler): void
{
$method = strtoupper($method);
$this->routes[$method][$path] = $handler;
}
private function handleRequest(): void
{
$requestMethod = $_SERVER['REQUEST_METHOD'];
$requestPath = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH);
$handler = $this->routes[$requestMethod][$requestPath] ?? null;
if ($handler) {
[$controller, $methodName] = $handler;
$method = new \ReflectionMethod($controller, $methodName);
$params = $this->getParams();
try {
$args = [];
foreach ($method->getParameters() as $param) {
$name = $param->getName();
$type = $param->getType();
if (array_key_exists($name, $params)) {
$value = $this->convertType($params[$name], $type);
$args[] = $value;
} elseif ($param->isDefaultValueAvailable()) {
$args[] = $param->getDefaultValue();
} else {
throw new \Exception("Parâmetro obrigatório '{$name}' não fornecido.");
}
}
$response = $method->invokeArgs($controller, $args);
$this->sendResponse($response);
} catch (\Exception $e) {
$this->sendResponse(['error' => $e->getMessage()], 400);
}
} else {
$this->sendResponse(['error' => 'Not Found'], 404);
}
}
private function getParams(): array
{
$data = [];
$method = $_SERVER['REQUEST_METHOD'];
$contentType = $_SERVER['CONTENT_TYPE'] ?? '';
if (in_array($method, ['GET', 'HEAD'])) {
$data = $_GET;
} else {
if (strpos($contentType, 'application/json') !== false) {
$json = file_get_contents('php://input');
$data = json_decode($json, true) ?? [];
} else {
parse_str(file_get_contents('php://input'), $data);
}
// Mesclar com parâmetros de URL (query string)
$data = array_merge($_GET, $data);
}
return $data;
}
private function sendResponse($data, int $statusCode = 200): void
{
http_response_code($statusCode);
header('Content-Type: application/json');
echo json_encode($data);
}
private function convertType($value, $type)
{
if ($type && !$type->isBuiltin()) {
throw new \Exception("Tipo de parâmetro não suportado: {$type}");
}
if ($type) {
$typeName = $type->getName();
return match ($typeName) {
'int' => (int) $value,
'float' => (float) $value,
'bool' => filter_var($value, FILTER_VALIDATE_BOOLEAN),
'string' => (string) $value,
'array' => (array) $value,
default => $value,
};
}
return $value;
}
}
<?php
require_once 'FastPHP.php';
require_once 'Attributes.php';
use FastPHP\Attributes\Route;
class MyAPI
{
#[Route('GET', '/soma')]
public function soma(float $a, float $b): array
{
return ['resultado' => $a + $b];
}
#[Route('POST', '/multiplica')]
public function multiplica(float $a, float $b): array
{
return ['resultado' => $a * $b];
}
#[Route('PUT', '/atualiza')]
public function atualiza(int $id, array $dados): array
{
// Lógica para atualizar um recurso
return ['id' => $id, 'dados' => $dados];
}
#[Route('DELETE', '/remove')]
public function remove(int $id): array
{
// Lógica para remover um recurso
return ['status' => 'Recurso removido', 'id' => $id];
}
#[Route('PATCH', '/modifica')]
public function modifica(int $id, array $dados): array
{
// Lógica para modificar parcialmente um recurso
return ['id' => $id, 'dados' => $dados];
}
}
FastPHP\FastPHP::run();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment