PHPackages                             liyuze/method-chaining-proxy - 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. [Utility &amp; Helpers](/categories/utility)
4. /
5. liyuze/method-chaining-proxy

ActiveLibrary[Utility &amp; Helpers](/categories/utility)

liyuze/method-chaining-proxy
============================

通过代理方式实现方法链式调用，消除控制语句对链式的影响。

1.1.0(4y ago)0101MITPHPPHP ^8.0

Since May 4Pushed 4y ago1 watchersCompare

[ Source](https://github.com/liyuze/method-chaining-proxy)[ Packagist](https://packagist.org/packages/liyuze/method-chaining-proxy)[ Docs](https://github.com/liyuze/method-chaining-proxy)[ RSS](/packages/liyuze-method-chaining-proxy/feed)WikiDiscussions main Synced 3w ago

READMEChangelogDependencies (1)Versions (3)Used By (1)

PHP 方法链式调用代理
============

[](#php-方法链式调用代理)

[![Latest Version on Packagist](https://camo.githubusercontent.com/4c82d167104263b39e9946191ac367e10b271262bd72ed0ca62afac5d1773f34/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f6c6979757a652f6d6574686f642d636861696e696e672d70726f78792e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/liyuze/method-chaining-proxy)[![Total Downloads](https://camo.githubusercontent.com/42bac1f44249d7ad5c1acf155ea938958cd117929578d69299f41ddf2c08f733/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f64742f6c6979757a652f6d6574686f642d636861696e696e672d70726f78792e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/liyuze/method-chaining-proxy)[![PHP Composer](https://github.com/liyuze/method-chaining-proxy/actions/workflows/php.yml/badge.svg?branch=main&event=push)](https://github.com/liyuze/method-chaining-proxy/actions/workflows/php.yml)

流式接口（fluent interface）是软件工程中面向对象API的一种实现方式，以提供更为可读的源代码。方法链式调用（method chaining）是流式接口的一种实现。 在 PHP 中的实现方式是在类的方法返回值中返回 `$this` 或 `new static()` 来实现方法链式调用。

本扩展包尝试解决：

1. 传统返回值（无 `return` 或有 `return` 的值非本类对象）下实现链式调用。
2. 通过"强制"忽略（tap 模式）或关注（pipe 模式）返回值实现更加灵活的链式调用。
3. 优化控制语句（if/switch/foreach/while）对链式调用在代码层级中断。

> 关于代码提示：PHPStorm [暂不支持在@template 时同时使用 @mixin 语句](https://youtrack.jetbrains.com/issue/WI-64022/Support-mixin-with-template)，所以无法实现代码自动提示功能。如果你有更好实现代码提示的方法，欢迎与我联系~😃 ！！！过度使用本包可能影响代码的可读性和增加程序调试难度，建议在简单的逻辑中使用。

灵感
--

[](#灵感)

灵感来源于 laravel 的 `tap` 和 `pipe` 方法。

```
/**
 * Call the given Closure with the given value then return the value.
 *
 * @param  mixed  $value
 * @param  callable|null  $callback
 * @return mixed
 */
function tap($value, $callback = null)
{
    if (is_null($callback)) {
        return new HigherOrderTapProxy($value);
    }

    $callback($value);

    return $value;
}
```

```
namespace Illuminate\Support\Traits;

trait EnumeratesValues
{
    ...
    /**
     * Pass the collection to the given callback and return the result.
     *
     * @param  callable  $callback
     * @return mixed
     */
    public function pipe(callable $callback)
    {
        return $callback($this);
    }
    ...
}
```

安装
--

[](#安装)

你可以通过 composer 进行安装:

```
composer require liyuze/method-chaining-proxy
```

用例
--

[](#用例)

### 快速创建代理器

[](#快速创建代理器)

#### mixed 代理器

[](#mixed-代理器)

创建代理器

```
$cat = new Cat('Tom', 5);
$proxy = MethodChainingFactory::create($cat);
//或
$proxy = MethodChainingFactory::mixed($cat);
```

默认创建的是 `mixedMode` 的代理器，特点是如果调用的方法\*\*没有返回值或返回值是`null`\*\*时不会更新代理器的代理值。

```
$proxy = $proxy->setAge(9)->setName('Tony')->getName();
$proxy->popValue(); //Tony
$cat->getName();    //Tony
```

#### tap 模式代理器

[](#tap-模式代理器)

也可以通过 `tapMode()` 方法创建一个**忽略任何返回值**，代理器值一直不变的值代理器。

```
$cat = new Cat('Tom', 5);
$proxy = MethodChainingFactory::tap($cat);
$proxy = $proxy->setAge(9)->setName('Tony')->getName();
$proxy->popValue(); //Cat('Tony', 9)
$cat->getName();    //Tony
```

#### pipe 模式代理器

[](#pipe-模式代理器)

也可以通过 `pipeMode()` 方法创建一个接受**任何返回值**代理器。

```
$cat = new Cat('Tom', 5);
$proxy = MethodChainingFactory::pipe($cat);
$proxy = $proxy->setAge(9);
$proxy->popValue(); //null
$cat->getName();    //Tony
```

### 切换代理器模式

[](#切换代理器模式)

可以通过 'switchMixedMode()'、'switchTapMode()'、'switchPipeMode()' 方法来切换代理器的代理模式。

```
$cat = new Cat('Tom', 5);
$proxy = MethodChainingFactory::tap($cat);
$proxy = $proxy->switchToPipeMode()->getName();;
$proxy->popValue(); //Tom
$cat->getName();    //Tom
```

> 可以使用 `mixed`、`tap`、`pipe` 属性访问方式来调用对应的切换代理方法。

如果临时切换代理模式的情况，可以通过'tapOnce()'、'pipeOnce()'制定，所制定的调用方法仅会生效一次。

```
$cat = new Cat('Tom', 5);
$proxy = MethodChainingFactory::tap($cat);
$proxy = $proxy->pipeOnce()->getName()
$proxy->popValue(); //Tom
$cat->getName();    //Tom
```

> 可以使用 `tapOnce`、`pipeOnce` 属性访问方式来调用对应的单次切换代理方法。

### 摘取

[](#摘取)

可以通过 `pick()` 方法在方法链式调用过程中通过引用传值的方法获取某个属性值。

```
$cat = new Cat('Tom', 5);
$name = null;
$proxy = MethodChainingFactory::create($cat);
$proxy->setAge(9)->pick('name', $name)->setName('Tony');
$name; //Tom
$cat->getName();    //Tony
```

对于方法的值，可以通过 `methodPick()` 来摘取。

```
$cat = new Cat('Tom', 5);
$name = null;
$proxy = MethodChainingFactory::create($cat);
$proxy = $proxy->setAge(9)->methodPick($name, 'getName')->setName('Tony');;
$name; //Tom
$cat->getName();    //Tony
```

### 后置操作

[](#后置操作)

通过调用 `after()` 方法传入一个闭包来执行自定义的代码功能，它也支持链式调用。

闭包的第一个参数是当前代理器 `代理值`，如果闭包有返回值且不为null时将会更新代理器的代理值。

```
$cat = new Cat('Tom', 5);
$birthMonth = 3;
$proxy = MethodChainingFactory::create($cat);
$proxy = $proxy->setAge(9)->setName('Tony')->after(
    function ($proxyValue) use ($birthMonth) {
        //6月前出生的加1岁
        if ($birthMonth < 6) {
            $proxyValue->setAge($proxyValue->getAge() + 1);
        }
    });//->after(...)->after(...);

$proxy->popValue()->getAge();   // 10

$number = MethodChainingFactory::create($cat)->after(fn () => 3)->popValue();
// 3
```

### If 逻辑代理器

[](#if-逻辑代理器)

当给定的判定值为真时才会运行后续方法链的代理器。

```
$ifProxy = ControlChainingFactory::if(new Cat('Tom', 5), false);
// 或 $ifProxy = new IfChainingProxy(new Cat('Tom', 5), false);
$ifProxy->setName('Tony')
    ->elseChaining()
    ->setName('Alan');

$ifProxy->endSwitchChaining()->getName();   //Alan
```

也可以通过 `ControlChainingFactory::unless()` 创建一个判定值为假时才会运行后续方法链的代理器。

### Switch 逻辑代理器

[](#switch--逻辑代理器)

当给定的判定值与 `caseChaining()` 传入的值相等时才会运行后续方法链的代理器。

```
$switchProxy = ControlChainingFactory::switch(new Cat('Tom', 5), 2);
// 或 $switchProxy = new SwitchChainingProxy(new Cat('Tom', 5), 2);
$cat = $switchProxy
    ->caseChaining(1)->setName('Tony')
    ->caseChaining(2)->setName('Alan')
    ->endSwitchChaining();

$cat->getName();   //Alan
$cat->getAge();   //10
```

通过 `breakChaining()` 中断以后代码的执行。

> `breakChaining(2)` 方法支持传入要中断的循环层级数量，中断效果只针对 `MethodChainingProxy` 类嵌套有效，不兼容原生的控制语句。

```
 $switchProxy = ControlChainingFactory::switch(new Cat('Tom', 5), 2);
// 或 $switchProxy = new SwitchChainingProxy(new Cat('Tom', 5), 2);
$cat = $switchProxy
    ->caseChaining(1)->setName('Tony')->breakChaining()
    ->caseChaining(2)->setName('Alan')
    ->caseChaining(2)->setAge(10)->breakChaining()
    ->caseChaining(2)->setName('Andy')
    ->endSwitchChaining();

$cat->getName();   //Alan
$cat->getAge();   //10
```

通过 `defaultChaining() 指定默认要执行的代码。

```
 $switchProxy = ControlChainingFactory::switch(new Cat('Tom', 5), 2);
// 或 $switchProxy = new SwitchChainingProxy(new Cat('Tom', 5), 2);
$cat = $switchProxy
    ->caseChaining(1)->setName('Tony')->breakChaining()
    ->defaultChaining()->setName('Alan')->setAge(10)
    ->endSwitchChaining();

$cat->getName();   //Alan
$cat->getAge();   //10
```

### 示例类

[](#示例类)

```
class Cat
{
    public string $name;
    public int $age;

    public function __construct(string $name, int $age)
    {
        $this->name = $name;
        $this->age = $age;
    }

    public function getName()
    {
        return $this->name;
    }

    public function getAge()
    {
        return $this->age;
    }

    public function setName(string $name)
    {
        $this->name = $name;
    }

    public function setAge(int $age)
    {
        $this->age = $age;
    }

    public function setNameForChaining(string $name)
    {
        $this->name = $name;
        return $this;
    }

    public function setAgeForChaining(int $age)
    {
        $this->age = $age;
        return $this;
    }

    public function do(\Closure $closure)
    {
        $closure();

        return $this;
    }
}
```

### 测试

[](#测试)

```
composer test
```

### 修改记录

[](#修改记录)

点击 [CHANGELOG](CHANGELOG.md) 查看最近修改了哪些内容。

贡献
--

[](#贡献)

点击 [CONTRIBUTING](CONTRIBUTING.md) 查看详情

### 安全

[](#安全)

如果您发现任何与安全相关的问题，请发送电子邮件而不是使用问题追踪器。

贡献值
---

[](#贡献值)

- [Yuze Li](https://github.com/liyuze)
- [All Contributors](../../contributors)

开源协议
----

[](#开源协议)

The MIT License (MIT)。点击 [License File](LICENSE.md) 查看更多信息。

PHP Package 模板
--------------

[](#php-package-模板)

本扩展包使用 [PHP Package Boilerplate](https://laravelpackageboilerplate.com) 工具生成，该工具由 [Beyond Code](http://beyondco.de/) 提供。

###  Health Score

24

—

LowBetter than 31% of packages

Maintenance20

Infrequent updates — may be unmaintained

Popularity5

Limited adoption so far

Community9

Small or concentrated contributor base

Maturity55

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 ~2 days

Total

2

Last Release

1508d ago

### Community

Maintainers

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

---

Top Contributors

[![liyuze](https://avatars.githubusercontent.com/u/4597092?v=4)](https://github.com/liyuze "liyuze (23 commits)")

---

Tags

phpmethod-chainingmethod chaining proxy

###  Code Quality

TestsPHPUnit

### Embed Badge

![Health badge](/badges/liyuze-method-chaining-proxy/health.svg)

```
[![Health](https://phpackages.com/badges/liyuze-method-chaining-proxy/health.svg)](https://phpackages.com/packages/liyuze-method-chaining-proxy)
```

###  Alternatives

[imanghafoori/laravel-anypass

A minimal yet powerful package to help you in development.

21422.6k](/packages/imanghafoori-laravel-anypass)

PHPackages © 2026

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