承接 respect/fluent 相关项目开发

从需求分析到上线部署,全程专人跟进,保证项目质量与交付效率

邮箱:yvsm@zunyunkeji.com | QQ:316430983 | 微信:yvsm316

respect/fluent

Composer 安装命令:

composer require respect/fluent

包简介

Namespace-aware fluent class resolution

README 文档

README

Respect\Fluent

Build fluent interfaces from class namespaces. PHP 8.5+, zero dependencies.

Fluent maps method calls to class instances. You define classes in a namespace, extend FluentBuilder, and get a chainable API where each call resolves a class name, instantiates it, and accumulates it immutably.

$stack = Middleware::cors('*')
    ->rateLimit(100)
    ->auth('bearer')
    ->jsonBody();

$stack->getNodes(); // [Cors('*'), RateLimit(100), Auth('bearer'), JsonBody()]

Middlewares, validators, processors: anything that composes well as a chain can leverage Respect/Fluent.

Installation

composer require respect/fluent

Quick Start

1. Choose a namespace and interface

Fluent discovers classes from one or more namespaces. Giving them a shared interface lets your builder enforce type safety and expose domain methods.

namespace App\Middleware;

interface Middleware
{
    public function process(Request $request, Handler $next): Response;
}

final readonly class Cors implements Middleware
{
    public function __construct(private string $origin = '*') {}
    public function process(Request $request, Handler $next): Response { /* ... */ }
}

final readonly class RateLimit implements Middleware
{
    public function __construct(private int $maxRequests = 60) {}
    public function process(Request $request, Handler $next): Response { /* ... */ }
}
// etc...

2. Extend FluentBuilder

The #[FluentNamespace] attribute declares where your classes live and how to resolve them. The builder inherits __call, immutable accumulation, and withNamespace support, you only add domain logic:

namespace App;

use Respect\Fluent\Attributes\FluentNamespace;
use Respect\Fluent\Builders\Append;
use Respect\Fluent\Factories\NamespaceLookup;
use Respect\Fluent\Resolvers\Ucfirst;
use App\Middleware\Middleware;

#[FluentNamespace(new NamespaceLookup(new Ucfirst(), Middleware::class, 'App\\Middleware'))]
final readonly class MiddlewareStack extends Append
{
    public function __construct(Middleware ...$layers)
    {
        parent::__construct(static::factoryFromAttribute(), ...$layers);
    }

    /** @return array<int, Middleware> */
    public function layers(): array
    {
        return $this->getNodes();
    }
}

The attribute carries the full factory configuration: the resolver (Ucfirst), optional type constraint (Middleware::class), and namespace to search. The inherited factoryFromAttribute() reads it at runtime so there's a single source of truth.

Now MiddlewareStack::cors()->auth('bearer')->jsonBody() builds the layers for you.

3. Add composition if you want

Prefix composition lets optionalAuth() create Optional(Auth()). You're not limited to Optional cases, you can design nesting as deep as you want.

Annotate wrapper classes with #[Composable]:

namespace App\Middleware;

use Respect\Fluent\Attributes\Composable;

#[Composable(self::class)]
final readonly class Optional implements Middleware
{
    public function __construct(private Middleware $inner) {}

    public function process(Request $request, Handler $next): Response
    {
        // Skip the middleware if a condition is met
        return $this->shouldSkip($request)
            ? $next($request)
            : $this->inner->process($request, $next);
    }
}

Then switch the attribute to use ComposingLookup, it automatically discovers #[Composable] prefixes from the same namespace:

use Respect\Fluent\Factories\ComposingLookup;

#[FluentNamespace(new ComposingLookup(
    new NamespaceLookup(new Ucfirst(), Middleware::class, 'App\\Middleware'),
))]
final readonly class MiddlewareStack extends Append { /* ... */ }

Now MiddlewareStack::optionalAuth('bearer') creates Optional(Auth('bearer')).

4. Add custom namespaces

Users can extend your middleware stack with their own classes. withNamespace is inherited from FluentBuilder:

$stack = MiddlewareStack::cors();
$extended = $stack->withNamespace('MyApp\\CustomMiddleware');
$extended->logging();  // Finds MyApp\CustomMiddleware\Logging

How It Works

Fluent has three layers:

  • Resolvers transform method names before lookup (e.g., 'email''Email', or 'notEmail' → wrapper 'Not' + inner 'Email').
  • Factories search namespaces for the resolved class name and instantiate it.
  • Builders (Append, Prepend) chain factory calls immutably via __call.

Resolved classes are called nodes because consumer libraries (like Respect/Validation) often arrange them into tree structures.

A FluentNode carries the resolution state between resolvers and factories: a name, constructor arguments, and an optional wrapper.

                         +----------+
  'notEmail' -------->   | Resolver |  ------>  FluentNode('Email', wrapper: FluentNode('Not'))
                         +----------+
                              |
                              v
                         +----------+
  FluentNode --------->  | Factory  |  ------>  Not(Email())
                         +----------+

NamespaceLookup vs ComposingLookup: use NamespaceLookup for simple name-to-class mapping. Wrap it with ComposingLookup when you need prefix composition like notEmail()Not(Email()). ComposingLookup supports recursive unwrapping, so notNullOrEmail()Not(NullOr(Email())) works too.

Assurance attributes

Node classes can declare what they assure about their input via #[Assurance]. Assertion methods are marked with #[AssuranceAssertion], and #[AssuranceParameter] identifies specific parameters. Constructor parameters for composition use #[ComposableParameter].

This metadata is available at runtime through reflection and is also consumed by tools like FluentAnalysis for static type narrowing.

#[Assurance(type: 'int')]
final readonly class IntType implements Validator { /* ... */ }

final readonly class ValidatorBuilder extends Append
{
    #[AssuranceAssertion]
    public function assert(#[AssuranceParameter] mixed $input): void { /* ... */ }

    #[AssuranceAssertion]
    public function isValid(#[AssuranceParameter] mixed $input): bool { /* ... */ }
}

See Assurance, AssuranceParameter, ComposableParameter, and the enum types in the API reference for the full set of options.

API Reference

See docs/api.md for the complete API reference covering attributes, builders, factories, resolvers, and exceptions.

respect/fluent 适用场景与选型建议

respect/fluent 是一款 基于 PHP 开发的 Composer 扩展包,目前已累计 375 次下载、GitHub Stars 达 1, 最近一次更新时间为 2026 年 03 月 23 日, 在 PHP 生态内属于活跃度较高的组件。

它主要适用于以下技术方向: 「fluent」 「respect」 「builder」 等业务场景。在实际项目中,围绕这些方向常见需要落地的问题包括:接口对接、性能调优、并发安全、与既有框架(Laravel / ThinkPHP / Yii / Webman 等)的兼容适配,以及生产环境的日志埋点与稳定性保障。

我们在过去多个企业项目中使用过 respect/fluent 或与其功能相近的方案,如果你在选型或落地过程中遇到问题,例如 版本兼容、二次改造、私有化封装、与内部系统对接、生产 BUG 排查,欢迎联系我们协助评估。

围绕 respect/fluent 我们能提供哪些服务?
定制开发 / 二次开发

基于 respect/fluent 在你已有业务上做功能扩展、字段裁剪、UI 适配、与内部账号 / 权限 / 日志系统的深度对接。

BUG 修复 & 性能优化

线上偶发问题、内存泄漏、慢查询、并发异常等排查修复;针对高流量场景做缓存、队列、索引层面的调优。

项目外包 & 长期维护

承接完整的项目从需求 → 设计 → 开发 → 上线 → 长期运维;也可按月提供技术保姆服务。

yvsm@zunyunkeji.com QQ:316430983 微信:yvsm316 西安尊云信息科技 · 专注 PHP / Go / 分布式系统研发

统计信息

  • 总下载量: 375
  • 月度下载量: 0
  • 日度下载量: 0
  • 收藏数: 1
  • 点击次数: 34
  • 依赖项目数: 3
  • 推荐数: 1

GitHub 信息

  • Stars: 1
  • Watchers: 1
  • Forks: 1
  • 开发语言: PHP

其他信息

  • 授权协议: ISC
  • 更新时间: 2026-03-23