PHPackages                             zolta/http - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [HTTP &amp; Networking](/categories/http)
4. /
5. zolta/http

ActiveLibrary[HTTP &amp; Networking](/categories/http)

zolta/http
==========

Domain-driven HTTP framework for PHP 8.2+ with attribute-based routing, automatic request validation, DTO mapping, standardized response shaping, and built-in authorization. First-class Laravel and Symfony adapters.

v1.0.0(1mo ago)16↓100%MITPHPPHP ^8.2

Since Apr 25Pushed 1mo agoCompare

[ Source](https://github.com/zoltasoft/http)[ Packagist](https://packagist.org/packages/zolta/http)[ RSS](/packages/zolta-http/feed)WikiDiscussions main Synced 1w ago

READMEChangelogDependencies (14)Versions (2)Used By (0)

Zolta HTTP
==========

[](#zolta-http)

**Declarative APIs. Zero boilerplate.**

Define your entire HTTP pipeline — routing, validation, service binding, authorization, and response shaping — with PHP 8 attributes. Your controller methods stay empty. The framework does the wiring.

```
#[Route(path: 'users/{id}', methods: ['GET'], auth: 'sanctum', authorized: ['can_manage_users'])]
#[Request(GetUserByIdRequest::class, GetUserByIdDTO::class)]
#[Service(GetUserByIdService::class, 'User found.', 200)]
#[Response(UserResource::class)]
#[Doc(summary: 'Get a user by ID')]
public function show() {}  // That's it. The entire endpoint.
```

First-class Laravel (Symfony support coming soon) adapters. OpenAPI generation from the same attributes. Under 2ms pipeline overhead.

---

Why Zolta HTTP?
---------------

[](#why-zolta-http)

### The problem

[](#the-problem)

PHP frameworks give you routing and controllers, but the plumbing between "HTTP request" and "business logic" is still manual. Every endpoint repeats the same pattern: validate input → map to DTO → call service → transform result → shape response. This boilerplate multiplies across hundreds of endpoints, and every copy is a place for inconsistencies to hide.

### What Zolta HTTP does differently

[](#what-zolta-http-does-differently)

ApproachHow it worksTrade-offLaravel Resource ControllersConvention-based CRUD + manual service callsStill wiring validation, DTOs, responses by handSymfony API PlatformSchema-driven REST/GraphQL generationHeavy, opinionated, hard to customize beyond CRUDSpatie Query BuilderQuery parameter parsing for EloquentRead-only filtering, no full pipeline**Zolta HTTP****Full pipeline declared in attributes — routing to response****True zero-boilerplate endpoints, dual framework support**The key insight: your controller method shouldn't *contain* the pipeline — it should *declare* it. Five attributes replace what typically takes 30-50 lines of wiring code per endpoint.

### Who is this for?

[](#who-is-this-for)

- Teams building **API-first applications** who are tired of repetitive controller boilerplate
- Projects targeting **both Laravel and Symfony** with shared HTTP logic
- Developers who want **convention with escape hatches** — use attributes for 90% of endpoints, drop to manual for the rest

Install
-------

[](#install)

```
composer require zolta/http
```

Laravel auto-discovers the service provider. For Symfony, register the bundle in `config/bundles.php`.

---

The pipeline — from request to response
---------------------------------------

[](#the-pipeline--from-request-to-response)

Every attribute-routed request flows through a deterministic pipeline:

```
HTTP Request
  ↓ RouteMetadataResolver   — Combine class + method attributes (cached)
  ↓ RouteConfigValidator     — Validate controller setup
  ↓ Authorization            — Check gates from #[Route] authorized
  ↓ FormRequest validation   — Apply rules from #[Request]
  ↓ DTO mapping              — Map validated data to typed object
  ↓ ServiceInvoker           — Call the bound service class
  ↓ ResourceTransformer      — Apply #[Response] resource transformation
  ↓ ResponseFactory          — Wrap in standardized envelope
HTTP Response

```

Each step is independently replaceable. The entire pipeline adds **&lt; 2ms overhead** on warm requests.

---

Quick start
-----------

[](#quick-start)

### 1. Define a controller

[](#1-define-a-controller)

Controllers are **declaration sites**, not logic containers. Each method declares *what* should happen via attributes — the framework handles *how*:

```
use Zolta\Http\Controller\Controller;
use Zolta\Http\Router\Attributes\Route;
use Zolta\Http\Request\Attributes\Request;
use Zolta\Http\Service\Attributes\Service;
use Zolta\Http\Response\Attributes\Response;
use Zolta\Http\Service\Attributes\Doc;

final class UserController extends Controller
{
    #[Route(path: 'users/{id}', methods: ['GET'], auth: 'sanctum', authorized: ['can_manage_users'])]
    #[Request(GetUserByIdRequest::class, GetUserByIdDTO::class)]
    #[Service(GetUserByIdService::class, 'User found.', 200)]
    #[Response(UserResource::class)]
    #[Doc(summary: 'Get a user by ID')]
    public function show() {}
}
```

### 2. Define a form request

[](#2-define-a-form-request)

```
use Zolta\Http\Request\BaseRequest;

final class GetUserByIdRequest extends BaseRequest
{
    public function rules(): array
    {
        return ['id' => 'required|string|min:1'];
    }

    public function routeParams(): array
    {
        return ['id' => ['type' => 'string', 'required' => true]];
    }
}
```

### 3. Define an input DTO

[](#3-define-an-input-dto)

```
use Zolta\Support\Application\DTO\Input\InputDTO;
use Zolta\Support\Application\Attributes\FromRequest;

class GetUserByIdDTO extends InputDTO
{
    final public function __construct(
        #[FromRequest('id')]
        public readonly string $id,
        public readonly array $options = []
    ) {}
}
```

### 4. Define a resource

[](#4-define-a-resource)

```
use Zolta\Http\Response\Resources\Resource;

final class UserResource extends Resource
{
    public function toArray(): array
    {
        return [
            'user' => $this->all()['user'],
        ];
    }
}
```

Attribute reference
-------------------

[](#attribute-reference)

AttributeTargetPurpose`#[Route]`Class / MethodDefines path, HTTP methods, middleware, auth, authorization`#[Request]`Class / MethodBinds a form request class and optional input DTO`#[Service]`Class / MethodBinds a service class, success message, and HTTP status`#[Response]`Class / MethodBinds a resource class for response transformation`#[Doc]`Class / MethodOpenAPI documentation metadata (summary, description, tags)`#[View]`Class / MethodServer-side view rendering (view name, engine)Authorization
-------------

[](#authorization)

Configure the `AuthorizationMatrix` to map abilities to permissions, with multi-path extraction from your user model:

```
AuthorizationMatrix::configure([
    'abilities' => [
        'can_manage_users' => ['users.read', 'users.write'],
    ],
    'user' => [
        'class' => User::class,
        'attributes' => ['permissions', 'role.permissions', 'roles.*.permissions'],
    ],
]);
```

Then reference abilities in your route attribute — authorization is checked before the service is invoked:

```
#[Route(path: '/users/{id}', auth: 'sanctum', authorized: ['can_manage_users'])]
```

Response format
---------------

[](#response-format)

All responses follow a consistent envelope — success, error, and debug states share the same shape:

```
{
    "success": true,
    "message": "User found.",
    "data": { "user": { "id": "123", "name": "John" } },
    "errors": [],
    "debug": []
}
```

Exceptions are automatically normalized: domain exceptions (404, 409, 422) pass through with context; unexpected errors become safe 500 responses with debug trace in development mode.

---

What else is included
---------------------

[](#what-else-is-included)

### OpenAPI generation from attributes

[](#openapi-generation-from-attributes)

The same `#[Route]`, `#[Request]`, `#[Response]`, and `#[Doc]` attributes that drive runtime behavior also generate OpenAPI 3.0 specifications. No separate schema files to maintain — your docs always match your code.

### Multi-tier reflection caching

[](#multi-tier-reflection-caching)

Route metadata resolution uses a 3-tier cache: runtime memory → persistent store (Laravel Cache / APCu) → reflection fallback. Cold-start resolves once, then subsequent requests hit the cache at **&lt; 0.5ms**.

### Route caching with manifest tracking

[](#route-caching-with-manifest-tracking)

`AttributeRouteCache` compiles routes into `bootstrap/cache/attribute_routes.php` with file-level tracking — only changed controllers trigger rebuilds.

```
php artisan zolta:routes:cache    # Build route cache
php artisan zolta:routes:clear    # Clear route cache
php artisan zolta:routes:watch    # Watch for file changes in development
```

### Exception handling

[](#exception-handling)

The `HandlesApiExceptions` trait normalizes all exceptions into the standard response envelope. Domain exceptions (`ValidationException`, `NotFoundException`, `ConflictException`) carry structured error data; framework exceptions are safely wrapped.

### File upload support

[](#file-upload-support)

`UploadedFileDTO` provides a framework-neutral representation with `clientOriginalName`, `clientMimeType`, `size`, `tmpPath`, and `error` — works identically on Laravel and Symfony.

---

Performance
-----------

[](#performance)

Benchmarked on a real application (Laravel 12, PHP 8.3, SQLite):

Pipeline stepTime (warm)RouteMetadataResolver1.3–1.9msRouteConfigValidator&lt; 0.01msServiceInvoker overhead&lt; 0.5msResourceTransformer0.5–0.7msResponseFactory0.5–0.6ms**Total HTTP pipeline overhead****&lt; 2ms**The rest of your request time is your application logic — Eloquent queries, external calls, business rules. The transport layer stays invisible.

---

Dual framework support
----------------------

[](#dual-framework-support)

Every module has independent Laravel adapter (Symfony support is coming soon). The same controller code runs on either framework without modification.:

FeatureLaravelSymfonyAttribute routing✅coming soonForm request validation✅coming soonDTO mapping✅coming soonAuthorization✅coming soonException handling✅coming soonResponse shaping✅coming soonView rendering✅coming soonOpenAPI generation✅coming soonRoute caching✅coming soonReflection caching✅coming soonWrite your controllers once, deploy on either framework.

---

QA
--

[](#qa)

```
composer run qa          # Full suite: lint + analyse + phpmd + rector + test
composer run test        # PHPUnit only
```

**146 tests, 323 assertions** covering routing attributes, authorization matrix, request mapping, response contracts, exception handling, caching, and security.

---

Part of the Zolta Ecosystem
---------------------------

[](#part-of-the-zolta-ecosystem)

Zolta HTTP is the **transport layer** — it wires HTTP to your application through clean attributes:

```
┌─────────────────────────────────────────────┐
│  zolta/http (Transport) ← you are here      │
│  Attribute-driven routing & response        │
├─────────────────────────────────────────────┤
│  zolta/cqrs (Application)                   │
│  Commands, queries, events, transactions    │
├─────────────────────────────────────────────┤
│  zolta/forge (Domain)                       │
│  Value Objects, rules, specs, entities      │
└─────────────────────────────────────────────┘

```

When used together: a request arrives → **HTTP** resolves the pipeline via attributes → **Forge** hydrates the command with validated VOs → **CQRS** dispatches through the bus, captures events, wraps transactions → **HTTP** transforms and returns the response. All of this happens with **&lt; 5ms of package overhead** and zero manual wiring.

PackageLayerLinkzolta/forgeDomain[`packages/forge`](../zolta-forge)zolta/cqrsApplication[`packages/cqrs`](../zolta-cqrs)**zolta/http****Transport**You are here---

Documentation
-------------

[](#documentation)

Full documentation is available in the [`docs/`](./docs/) directory, organized for serving via Nuxt Content.

License
-------

[](#license)

[MIT](LICENSE) © 2026 Redouane Taleb

###  Health Score

39

—

LowBetter than 84% of packages

Maintenance90

Actively maintained with recent releases

Popularity7

Limited adoption so far

Community6

Small or concentrated contributor base

Maturity46

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Unknown

Total

1

Last Release

46d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/751b94d8f42b73b4851757bbdb5eed691d145fb41e94df15ce3a69557ea9d8e7?d=identicon)[redouaneT](/maintainers/redouaneT)

---

Top Contributors

[![redouaneT](https://avatars.githubusercontent.com/u/96720720?v=4)](https://github.com/redouaneT "redouaneT (13 commits)")

---

Tags

httpresponsephpapisymfonylaravelroutingadapterauthorizationdtorequest validationAttribute Routingzoltaresponse-shaping

###  Code Quality

TestsPHPUnit

Static AnalysisPHPStan, Rector

Code StyleLaravel Pint

Type Coverage Yes

### Embed Badge

![Health badge](/badges/zolta-http/health.svg)

```
[![Health](https://phpackages.com/badges/zolta-http/health.svg)](https://phpackages.com/packages/zolta-http)
```

###  Alternatives

[api-platform/core

Build a fully-featured hypermedia or GraphQL API in minutes!

2.6k50.1M306](/packages/api-platform-core)[api-platform/symfony

Symfony API Platform integration

354.0M107](/packages/api-platform-symfony)[api-platform/serializer

API Platform core Serializer

244.3M70](/packages/api-platform-serializer)[sulu/sulu

Core framework that implements the functionality of the Sulu content management system

1.3k1.4M195](/packages/sulu-sulu)[craftcms/cms

Craft CMS

3.6k3.6M2.9k](/packages/craftcms-cms)[web-auth/webauthn-framework

FIDO2/Webauthn library for PHP and Symfony Bundle.

51090.8k2](/packages/web-auth-webauthn-framework)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
