PHPackages                             blackcube/yii-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. [API Development](/categories/api)
4. /
5. blackcube/yii-handler

ActiveLibrary[API Development](/categories/api)

blackcube/yii-handler
=====================

PSR-15 handler abstractions and pipeline for Yii3 applications

03PHP

Since May 2Pushed 1mo agoCompare

[ Source](https://github.com/blackcubeio/yii-handler)[ Packagist](https://packagist.org/packages/blackcube/yii-handler)[ RSS](/packages/blackcube-yii-handler/feed)WikiDiscussions devel Synced 1w ago

READMEChangelogDependenciesVersions (1)Used By (0)

Blackcube Yii Handler
=====================

[](#blackcube-yii-handler)

[![License](https://camo.githubusercontent.com/6cb285b57819f8de0acfb34923298f4f569f962544e8fe35331da2d163f4e485/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f6c6963656e73652d4253442d2d332d2d436c617573652d626c75652e737667)](LICENSE.md)[![Packagist Version](https://camo.githubusercontent.com/dff3cee7d997ca7abe44752c55e4d28beb48ffd6e0e4e551024d3fda1a022464/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f626c61636b637562652f7969692d68616e646c65722e737667)](https://packagist.org/packages/blackcube/yii-handler)

PSR-15 handler abstractions and pipeline for Yii3 applications.

Three layers of abstract handlers, each optional:

- **`AbstractHandler`** — base PSR-15 handler with view rendering, JSON, redirect, download, AJAX helpers and namespace-based view resolution.
- **`AbstractPipelineHandler`** — four-step pipeline (`setup → setupMethod → process → prepareOutputData → output`) with an immutable `Output` DTO.
- **`Dialog\AbstractDialogInit`** / **`AbstractDialogConfirm`** — AJAX dialog flow (submit → modal → confirm) backed by session.

Where it sits
-------------

[](#where-it-sits)

```
┌────────────────────────────────────────────┐
│         Your Yii3 application              │
│   (handlers extend the abstract bases)     │
└─────────────────────┬──────────────────────┘
                      ↓
              ┌───────────────┐
              │ yii-handler   │  ← this package
              │  (3 layers)   │
              └───────┬───────┘
                      ↓
        Yii3 / PSR-15 / PSR-7 services
        (WebViewRenderer, Aliases, Router…)

```

The Dialog layer additionally consumes `blackcube/yii-bleet`, `blackcube/yii-bridge-model` and `yiisoft/session` (declared as `suggest` — install only if you use it).

Requirements
------------

[](#requirements)

- PHP 8.1+
- Yii3 (`yiisoft/aliases`, `yiisoft/router`, `yiisoft/yii-view-renderer`, `yiisoft/data-response`, `yiisoft/http`)
- PSR-7, PSR-15, PSR-3
- For the Dialog layer: `blackcube/yii-bleet`, `blackcube/yii-bridge-model`, `yiisoft/session`

Installation
------------

[](#installation)

```
composer require blackcube/yii-handler
```

If you need the Dialog layer:

```
composer require blackcube/yii-bleet blackcube/yii-bridge-model yiisoft/session
```

What it is
----------

[](#what-it-is)

A small set of base classes that capture the patterns we keep reusing across every Blackcube Yii3 application:

- **Render a view** with a layout and a configurable view path.
- **Resolve view names** from the handler namespace — `Detail` in `App\Handlers\Admin\Articles\Detail` looks up `Admin/Articles/detail.php` automatically.
- **Run a structured pipeline** when a handler needs to load data, react to the HTTP verb, run business logic and produce a response.
- **Build AJAX dialogs** that submit a form, open a confirmation modal and confirm — without rewriting the session/validation dance every time.

The package is opinionated about *how* a handler is built, not about *what* it does.

Quick Start
-----------

[](#quick-start)

### A simple handler — extend `AbstractHandler`

[](#a-simple-handler--extend-abstracthandler)

```
namespace App\Handlers;

use Blackcube\Handler\AbstractHandler;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;

final class Home extends AbstractHandler
{
    public function handle(ServerRequestInterface $request): ResponseInterface
    {
        $this->request = $request;
        return $this->render('home', ['title' => 'Welcome']);
    }
}
```

### A pipeline handler — extend `AbstractPipelineHandler`

[](#a-pipeline-handler--extend-abstractpipelinehandler)

```
namespace App\Handlers\Admin\Articles;

use App\Models\Article;
use Blackcube\Handler\AbstractPipelineHandler;
use Blackcube\Handler\Output;
use Blackcube\Handler\OutputType;

final class Index extends AbstractPipelineHandler
{
    private array $articles = [];

    protected function setup(): ?Output
    {
        $this->articles = Article::query()
            ->andWhere(['deletedAt' => null])
            ->orderBy(['createdAt' => SORT_DESC])
            ->all();

        return null;
    }

    protected function process(): Output
    {
        return new Output(OutputType::Render, [
            'articles' => $this->articles,
        ], 'index');
    }
}
```

`process()` returns an `Output` describing **what** to render. The pipeline dispatches it to the right method (`render`, `renderPartial`, `renderJson`, `redirect`, download).

### A dialog handler — extend `Dialog\AbstractDialogInit`

[](#a-dialog-handler--extend-dialogabstractdialoginit)

```
namespace App\Handlers\Admin\Articles;

use App\Forms\ArticleDeleteForm;
use Blackcube\BridgeModel\BridgeFormModel;
use Blackcube\Handler\Dialog\AbstractDialogInit;
use Blackcube\Handler\Output;
use Blackcube\Handler\OutputType;

final class DeleteDialog extends AbstractDialogInit
{
    protected function getSessionPrefix(): string
    {
        return 'article_delete_';
    }

    protected function createForm(): BridgeFormModel
    {
        return new ArticleDeleteForm();
    }

    protected function handleSubmit(BridgeFormModel $form, ?array $bodyParams): Output
    {
        $confirmationId = $this->storeInSession([
            'bodyParams' => $bodyParams,
            'articleId' => $this->currentRoute->getArgument('id'),
        ]);

        return new Output(OutputType::Json, [
            'modalUrl' => $this->urlGenerator->generate('articles.delete.confirm', [
                'id' => $this->currentRoute->getArgument('id'),
                'confirmationId' => $confirmationId,
            ]),
        ]);
    }

    protected function handleInit(array $data, string $confirmationId): Output
    {
        // Render the modal content as JSON for the AJAX dialog widget.
        // See docs/dialog.md for the full example.
    }
}
```

Architecture
------------

[](#architecture)

LayerClassAddsUse it when1`AbstractHandler`render / json / redirect / download / AJAX helpers / view resolutionYou write a handler that does its own `handle()`2`AbstractPipelineHandler`4-step pipeline + `Output` DTO + `CurrentRoute`You want a structured handler with setup/process/output separation3`Dialog\AbstractDialogInit` + `AbstractDialogConfirm`Session-backed AJAX submit/confirm flowYou build a confirmation dialog (delete, validate, two-step action)Each layer extends the previous one. Pick the lowest layer that fits.

Configuration
-------------

[](#configuration)

```
use Blackcube\Handler\HandlerConfig;

new HandlerConfig(
    handlerNamespacePrefix: 'App\\Handlers\\',
    viewsAlias:             '@src/Views',
    layoutAlias:            '@src/Views/Layouts/main.php',
    debug:                  false,
);
```

PropertyDefaultUsed by`handlerNamespacePrefix``App\\Handlers\\``resolveView()` to map a handler class to a view subdirectory`viewsAlias``@src/Views``render()` / `renderPartial()` to set the view path`layoutAlias``@src/Views/Layouts/main.php``render()` to apply the layout`debug``false`Exposed as `$this->debug` for handlers that branch on itRegister a single `HandlerConfig` instance in your DI container; every handler receives it.

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

[](#documentation)

TopicFileOverview and contents[docs/index.md](docs/index.md)Installation and DI wiring[docs/installation.md](docs/installation.md)Three-layer architecture[docs/architecture.md](docs/architecture.md)`AbstractHandler` reference[docs/abstract-handler.md](docs/abstract-handler.md)`AbstractPipelineHandler` reference[docs/pipeline-handler.md](docs/pipeline-handler.md)Dialog handlers reference[docs/dialog.md](docs/dialog.md)Let's be honest
---------------

[](#lets-be-honest)

**Coupled to Yii3.**

The base handler depends on `WebViewRenderer`, `Aliases`, `UrlGeneratorInterface` from Yii3. It is not framework-agnostic. If you build on Slim or Laravel without the Yii3 view layer, this package is not for you.

**Opinionated view resolution.**

The `//path` convention (handler namespace → view subdirectory) is opinionated. It works very well when you keep handlers and views in mirrored folders, and not at all if you don't. The behavior is overridable but you will be fighting the defaults.

**The Dialog layer drags Bleet and BridgeModel.**

`Dialog\AbstractDialogInit` and `AbstractDialogConfirm` reference `AureliaCommunication`, `DialogAction`, `UiColor` from `blackcube/yii-bleet` and `BridgeFormModel` from `blackcube/yii-bridge-model`. They are declared as `suggest`, but you cannot use the Dialog layer without installing them. If you don't use Bleet, ignore this layer entirely.

**No tests yet.**

The package ships without a test suite. Coverage is on the roadmap.

License
-------

[](#license)

BSD-3-Clause. See [LICENSE.md](LICENSE.md).

Author
------

[](#author)

Philippe Gaultier

###  Health Score

20

—

LowBetter than 13% of packages

Maintenance61

Regular maintenance activity

Popularity3

Limited adoption so far

Community6

Small or concentrated contributor base

Maturity11

Early-stage or recently created project

 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.

### Community

Maintainers

![](https://avatars.githubusercontent.com/u/545714?v=4)[pgaultier](/maintainers/pgaultier)[@pgaultier](https://github.com/pgaultier)

---

Top Contributors

[![pgaultier](https://avatars.githubusercontent.com/u/545714?v=4)](https://github.com/pgaultier "pgaultier (1 commits)")

### Embed Badge

![Health badge](/badges/blackcube-yii-handler/health.svg)

```
[![Health](https://phpackages.com/badges/blackcube-yii-handler/health.svg)](https://phpackages.com/packages/blackcube-yii-handler)
```

###  Alternatives

[facebook/php-business-sdk

PHP SDK for Facebook Business

90923.5M35](/packages/facebook-php-business-sdk)[hubspot/api-client

Hubspot API client

24015.5M18](/packages/hubspot-api-client)[botman/driver-telegram

Telegram driver for BotMan

93452.6k6](/packages/botman-driver-telegram)

PHPackages © 2026

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