PHPackages                             pine3ree/pine3ree-invokable-request-handler - 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. pine3ree/pine3ree-invokable-request-handler

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

pine3ree/pine3ree-invokable-request-handler
===========================================

Autowired invokable server-request handlers

1.0.0(12mo ago)012BSD-3-ClausePHPPHP ^7.4 || ^8.0CI passing

Since Apr 30Pushed 11mo ago1 watchersCompare

[ Source](https://github.com/pine3ree/pine3ree-invokable-request-handler)[ Packagist](https://packagist.org/packages/pine3ree/pine3ree-invokable-request-handler)[ Docs](https://github.com/pine3ree/pine3ree-invokable-request-handler)[ RSS](/packages/pine3ree-pine3ree-invokable-request-handler/feed)WikiDiscussions master Synced 1mo ago

READMEChangelog (10)Dependencies (11)Versions (16)Used By (0)

pine3ree invokable request handler
==================================

[](#pine3ree-invokable-request-handler)

[![Continuous Integration](https://github.com/pine3ree/pine3ree-invokable-request-handler/actions/workflows/continuos-integration.yml/badge.svg)](https://github.com/pine3ree/pine3ree-invokable-request-handler/actions/workflows/continuos-integration.yml)

This package provides a psr server-request handler that can be invoked directly. Descendant classes or classes using the `InvokableRequestHandlerTrait` must implement the `__invoke` method, whose dependencies are resolved either using the request attributes or by the container, via the composed params-resolver. A type-hinted `ServerRequestInterface` dependency is resolved to the current request.

The default implementation requires the return type to be a psr-response object.

In scenarios where you might need to return other types, you will also need to override the default psr `handle` method and build a response object using the return value of the protected method `invokeHandler(ServerRequestInterface)`which is responsible for executing the handler itself after resolving its arguments.

How it works
------------

[](#how-it-works)

`$handler->handle($request)` calls protected method `$this->invokeHandler($request)`

`$this->invokeHandler($request)` resolve `__invoke` `$args` and calls `$this(...$args)`

Examples
--------

[](#examples)

### Signature example:

[](#signature-example)

```
namespace App\Handler;

use Psr\Http\Server\RequestHandlerInterface;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use pine3ree\Http\Server\InvokableRequestHandler;
// ...more use(s)

/**
 * An invokable controller for route '/shop/product/{id}'
 */
class MyRequestHandler extends InvokableRequestHandler // implements RequestHandlerInterface
{
    public function __invoke(
        // ServerRequestInterface $request, // this is optional...but at the end... it is a request-handler
        // type-hinted dependencies and optional named parameters matching request attributes names
    ): ResponseInterface {
        // do something with dependency and request and return a psr-response
    }
}
```

### Basic example:

[](#basic-example)

```
namespace App\Controller\Shop\Product;

use App\Model\Entity\Product;
use App\Model\ORMInterface;
use App\Session\SessionInterface;
use App\Http\Message\Response\HtmlResponse;
use App\Http\Message\Response\NotFoundResponse;
use App\View\TemplateRendererInterface;
use Psr\Http\Server\RequestHandlerInterface;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use RuntimeException;
use pine3ree\Http\Server\InvokableRequestHandler;

/**
 * An invokable controller for route '/shop/product/{id}'
 */
class Read extends InvokableRequestHandler implements RequestHandlerInterface
{
    public function __invoke(
        ServerRequestInterface $request,
        ORMInterface $orm,
        TemplateRendererInterface $view,
        SessionInterface $session, // stored as request attribute with the SessionInterface:class key
        ?int $id = null // Route-match parameter stored as request attribute with the 'id' key
    ): ResponseInterface {

        $id = $id ?? 0;
        if (id < 1) {
            return new NotFoundResponse();
        }

        $product = $orm->findById(Product::class, $id);

        if ($product === null) {
            return new NotFoundResponse("Product not found for id={$id}");
        }

        $session->set('last_visited_product_id', $id);

        return new HtmlResponse(
            $view->render('shop/product/read.html.php', [
                'product' => $product,
            ]);
        );
    }
}
```

### Same example using the provided trait when a custom constructor is needed:

[](#same-example-using-the-provided-trait-when-a-custom-constructor-is-needed)

```
namespace App\Controller\Shop\Product;

use App\Model\Entity\Product;
use App\Model\ORMInterface;
use App\Session\SessionInterface;
use App\Http\Message\Response\HtmlResponse;
//..
use Psr\Http\Server\RequestHandlerInterface;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
//..
use pine3ree\Http\Server\InvokableRequestHandlerTrait;

class Read implements RequestHandlerInterface
{
    use InvokableRequestHandlerTrait;

    private array $options;

    public function __construct(
        ParamsResolverInterface $paramsResolver,
        array $options
    ) {
        $this->paramsResolver = $paramsResolver;
        $this->options = $options;
    }

    public function __invoke(
        ServerRequestInterface $request,
        ORMInterface $orm,
        TemplateRendererInterface $view,
        SessionInterface $session, // stored as request attribute under the SessionInterface:class key
        ?int $id = null // Route-match parameter stored as request attribute with the 'id' key
    ): ResponseInterface {

        // Do something with $id

        // Do something using $this->options

        // Return a response
    }
}
```

### Examples of `__invoke()` not returning a response object:

[](#examples-of-__invoke-not-returning-a-response-object)

```
namespace App\Http\Server;

// ...
use App\Http\Message\Response\HtmlResponse;
use App\Http\Message\Response\JsonResponse;
use App\View\TemplateRendererInterface;
use Psr\Http\Server\RequestHandlerInterface;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use pine3ree\Http\Server\InvokableRequestHandler;

/**
 * Example of base invokable handler that returns rendered-templates strings for
 * html-responses
 */

abstract class TemplateInvokableRequestHandler extends InvokableRequestHandler implements RequestHandlerInterface
{
    // Override the default trait implementation using the protected method `invokeHandler`
    public function handle(ServerRequestInterface $request): ResponseInterface
    {
        return new HtmlResponse(
            $this->invokeHandler($request);
        );
    }

    /**
     * In this example the implementation must return strings
     *
     * public function __invoke(
     *     TemplateRendererInterface $view,
     *     // Other dependencies and/or route params here
     * ): string {
     *     // build the template $vars map here
     *     return $view->render('some/template/file.html.php', $vars);
     * }
     */
}

/**
 * Example of base invokable handler that returns arrays for json-responses
 */

abstract class JsonInvokableRequestHandler extends InvokableRequestHandler implements RequestHandlerInterface
{
    // Override the default trait implementation using the protected method `invokeHandler`
    public function handle(ServerRequestInterface $request): ResponseInterface
    {
        return new JsonResponse(
            $this->invokeHandler($request);
        );
    }

    /**
     * In this example the implementation must return arrays
     *
     * public function __invoke(
     *     // Dependencies and/or route params here
     * ): array {
     *     // build the json-content $vars map here
     *     return $vars;
     * }
     */
}
```

###  Health Score

30

—

LowBetter than 65% of packages

Maintenance51

Moderate activity, may be stable

Popularity5

Limited adoption so far

Community7

Small or concentrated contributor base

Maturity50

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

Every ~1 days

Total

15

Last Release

364d ago

Major Versions

0.9.x-dev → 1.0.02025-05-10

### Community

Maintainers

![](https://www.gravatar.com/avatar/ba4cd94c187112c16f80f5785a3cdf3703b6f6b578f27c3a0a1bb9b9b0c1ce43?d=identicon)[pine3ree](/maintainers/pine3ree)

---

Top Contributors

[![pine3ree](https://avatars.githubusercontent.com/u/3229979?v=4)](https://github.com/pine3ree "pine3ree (80 commits)")

---

Tags

request-handlerpine3ree

###  Code Quality

TestsPHPUnit

Static AnalysisPHPStan

Code StylePHP\_CodeSniffer

Type Coverage Yes

### Embed Badge

![Health badge](/badges/pine3ree-pine3ree-invokable-request-handler/health.svg)

```
[![Health](https://phpackages.com/badges/pine3ree-pine3ree-invokable-request-handler/health.svg)](https://phpackages.com/packages/pine3ree-pine3ree-invokable-request-handler)
```

###  Alternatives

[api-platform/state

API Platform state interfaces

223.4M57](/packages/api-platform-state)

PHPackages © 2026

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