cyber-duck/fluent-debug

此包已被废弃,不再维护。作者建议使用 cyber-duck/fluent-debug 包。

1.0.2 2017-02-17 19:56 UTC

This package is auto-updated.

Last update: 2023-09-08 11:20:56 UTC


README

此包将不再得到支持。

Fluent / 连接方法/函数 xDebug 库

## 为什么?

像 Laravel 这样的框架大量使用并鼓励方法连接。

考虑以下从 Laravel 框架中随机选取的一行代码

Finder::create()
->files()
->name('*.php')
->in($configPath) 

这看起来很漂亮。但有个问题。假设我对

Finder::create()
->files()
->name('*.php')

的返回值感兴趣,并希望用调试器检查它。

目前,我所知道的在 PHP 中使用 xDebug 来完成这个操作的唯一方法是逐行执行,或者费时费力地重写代码以引入中间变量,即把上面的代码重写为

$a = Finder::create()
->files()
->name('*.php')

//put breakpoint on this line:
$a->in($configPath) 

在这个例子中,这听起来并不特别困难,但很快就会变得一团糟。

让我们再考虑另一行随机代码

Chicken::load(meatProcess($sausage->bacon()));

假设我对这里的 $sausage->bacon() 的返回值感兴趣。我该在哪里设置断点来获取它?如果我把断点放在这行上,我就必须逐行执行对 bacon 的调用并截获返回值,这有时相当困难。或者,也许我可以把断点放在 meatProcess 调用的第一行上。第三种选择是做类似这样的事情

Chicken::load(meatProcess(($a = $sausage->bacon())->ketchup()));
$a;

然后在第二行上设置断点。但如果对 ketchup 的调用改变了 $a?你就会被误导!

无论如何,我再次弄乱了代码。

这类事情是为什么有些程序员总的来说反对方法连接——调试确实变得困难得多。

例如,参见 https://ocramius.github.io/blog/fluent-interfaces-are-evil/

但我们在现实世界中生活,这是一种流行的方法,如果做得好,就像 Laravel 一样,会使你的代码更容易阅读。

## 如何?

所以,这里我提出一个非常简单的扩展,我相信它消除了大多数由流畅方法连接引起的调试痛苦。

扩展分为两部分。首先是一个具有两个方法的 trait,即 debugBreakdebugBreakIf。这些方法实际上是 xdebug 安装的 xdebug_break 函数的包装。

使用方法如下

Finder::create()
->files()
->name('*.php')
->debugBreak()
->in($configPath) 

或者也许

Finder::create()
->files()
->name('*.php')
->debugBreakIf(2 === $a)
->in($configPath) 

或者确实

Finder::create()
->files()
->name('*.php')
->debugBreakIf(function(){return app()->isRunningUnitTests();))
->in($configPath) 

要使用此功能,请将 use CyberDuck\Traits\DebugsFluently 添加到任何你希望使用它(或其父类)的类中。在我的不断增长的待办事项列表中,有一个计划是自动将此添加到每个类中。

其次——主要用于函数链——是全局函数 debugBreakdebugBreakIf

上面的例子将变为

Chicken::load(meatProcess(debugBreak($sausage->bacon())->ketchup()));

或者有 debugBreakIf - 第二个参数的作用方式与 trait 中的 debugBreakIf 方法相同。

### 脚注

1: 有一种在 .NET 中完成此操作的方法——参见 https://davefancher.com/2016/01/28/functional-c-debugging-method-chains/