Laravel dd函数的限制

15

我有一个包含320个数组的数组,使用普通的var_dump可以展示所有嵌套元素,而Laravel的dd助手会在索引147处截断嵌套元素,并且后续的所有元素都被截断,没有展开它们的选项,如下例所示。

  146 => array:17 [▼
    "total_unconfirmed_subscribers" => 0
    "total_subscribers_subscribed_yesterday" => 0
    "unique_list_id" => "24324"
    "http_etag" => ""fbb6febfca8af5541541ea960aaedb""
    "web_form_split_tests_collection_link" => "https://api.com/1.0/"
    "subscribers_collection_link" => "https://api.com/1.0/"
    "total_subscribers_subscribed_today" => 0
    "id" => 23432
    "total_subscribed_subscribers" => 0
    "total_unsubscribed_subscribers" => 0
    "campaigns_collection_link" => "https://api.com/1.0/"
    "custom_fields_collection_link" => "https://api.com/1.0/accounts"
    "self_link" => "https://api.com/1.0/accounts"
    "total_subscribers" => 0
    "resource_type_link" => "https://api.com/1.0/#list"
    "web_forms_collection_link" => "https://api.com/"
    "name" => "dccode"
  ]
  147 => array:17 [▼
    "total_unconfirmed_subscribers" => 0
     …16
  ]
  148 => array:17 [ …17]
  149 => array:17 [ …17]

为什么限制为147个完整记录,如何增加限制?
相关主题Laravels的DD助手函数是否正常工作?并没有解释限制。
这是非常一致的行为,我已经在Linux(Laravel Forge,DO droplet,Ubuntu),Mac(Laravel Valet)和Windows(valet4windows)上使用Laravel 5.2和php7进行了测试。
每个地方都在第147个元素上得到了完全相同的切割。使用CLIphp artisan tinker输出相同的切割。
...
"name" => "dccode"   ]   147 => array:17 [
"total_unconfirmed_subscribers" => 0
 16   ]   148 => array:17 [ 17]
...

你有没有考虑使用 print_r() 代替? - Derek Pollard
var_dumpprint_r都可以正常工作,我不关心如何查看数据,我想了解dd的限制。 - vitr
你使用的是哪个 Laravel 版本?4.2 和 5.2 都可以返回 20,000 个元素。 - sleepless
这很奇怪。昨天我尝试了一下,甚至复制了你的可见数组,创建了一个for循环,以便我得到20,000个条目,然后使用dd进行转储。它在4.2和5.2中都可以工作。你尝试过用另一个数组吗?你也可以尝试在CLI中运行它。Laravel使用CLIDumper。 - sleepless
@sleepless kk,你能告诉我你的服务器配置、操作系统、PHP版本等信息吗?到目前为止,我已经在使用PHP 7进行测试,在Laravel Forge DO实例(覆盖Linux)和我的PC上使用Valet4Windows也是PHP 7(覆盖Windows)。很快我会在Mac上尝试,但我确信我会得到相同的结果,即在147条记录中出现截断。在CLI模式下,得到的截断结果完全相同:147 => array:17 [ "total_unconfirmed_subscribers" => 0 ÔǪ16 ] - vitr
显示剩余2条评论
4个回答

29

在版本 5.0 之前,Laravel 的dd()函数如下所示:

function dd()
{
    array_map(function($x) { var_dump($x); }, func_get_args()); die;
}

自5.0版本以来,它看起来像这样:

function dd()
{
    array_map(function ($x) {
        (new Dumper)->dump($x);
    }, func_get_args());

    die(1);
}
Dumper使用Symfony的VarCloner,它是扩展了AbstractCloner的。这个类有一个$maxItems属性,设置为2500。请参阅:https://github.com/symfony/var-dumper/blob/master/Cloner/AbstractCloner.php#L125 每个数组有17个项目。将其乘以147,您会得到2499。这就是为什么位于键147的数组在第一个项目之后被截断的原因。
如果您想增加它,您需要覆盖laravel的Dumper类(https://github.com/laravel/framework/blob/5.2/src/Illuminate/Support/Debug/Dumper.php)。
public function dump($value)
{
    if (class_exists(CliDumper::class)) {
        $dumper = 'cli' === PHP_SAPI ? new CliDumper : new HtmlDumper;

        $cloner = new VarCloner();
        $cloner->setMaxItems(5000);
        $dumper->dump($cloner->cloneVar($value));
    } else {
        var_dump($value);
    }
}

这真的很有效!解释得非常好,谢谢。您是否推荐一种更好的方法来覆盖我的自定义应用程序中的“dump”函数,而不影响任何供应商代码? - vitr
1
是的,很明显将其直接写入核心类是个不好的主意。那只是一个提示,以便你知道如何增加限制。现在基本上取决于你了。一种简单的方法是编写自己的dd函数。这很容易,因为laravel会检查该函数是否已存在:https://dev59.com/ll4b5IYBdhLWcg3w-10I#28475973 - 或者你需要创建一个扩展laravel Dumper的自定义Dumper。这就是我所说的“覆盖”的意思 :) - sleepless
最终我使用自定义的 AppDumper 类,并在我的帮助器中使用它的 dd 方法。在 boostrap/autoload.php 中,在主自动加载程序之前,通过 require __DIR__.'/../app/helpers.php'; 引入了这个类。 - vitr

9
我的建议是在 VarDumper 组件中添加一个 handler
在你的 AppServiceProvider.php 文件中: (在 class 声明之前)
use Symfony\Component\VarDumper\VarDumper;
use Symfony\Component\VarDumper\Cloner\VarCloner;
use Symfony\Component\VarDumper\Dumper\CliDumper;
use Symfony\Component\VarDumper\Dumper\HtmlDumper;

(在 boot() 方法内部)

VarDumper::setHandler(function ($var) {
    $cloner = new VarCloner();
    $cloner->setMaxItems(-1); // Specifying -1 removes the limit
    $dumper = 'cli' === PHP_SAPI ? new CliDumper() : new HtmlDumper();

    $dumper->dump($cloner->cloneVar($var));
});

根据Symfony的VarDumper组件文档setMaxItems() 配置将被克隆超过最小嵌套深度的最大项目数。使用广度优先算法计算项目,因此较低级别的项目比深度嵌套的项目具有更高的优先级。指定-1会删除限制。
在文档中,您可以看到其他自定义Cloners、Dumpers和Casters组件的方法。

7

我建议你在bootstrap文件夹中创建一个自定义的helpers文件。

1)按照以下答案创建一个自定义的辅助函数,如果太复杂,可以跳过以下步骤,在第2步中像任何普通函数一样使用我的函数并调用它 >> https://dev59.com/Tl4c5IYBdhLWcg3wHXNS#28290359

2) I would like to give some credits to this guy, I follow his guide to create my own ddd function >> https://tighten.co/blog/a-better-dd-for-your-tdd

use Illuminate\Support\Debug\HtmlDumper;
use Symfony\Component\VarDumper\Cloner\VarCloner;
use Symfony\Component\VarDumper\Dumper\CliDumper;

function ddd()
{
    $args = func_get_args();
    $defaultStringLength = -1;
    $defaultItemNumber = -1;
    $defaultDepth = -1;

    foreach ($args as $variable) {
        $dumper = 'cli' === PHP_SAPI ? new CliDumper() : new HtmlDumper();

        $cloner = new VarCloner();
        $cloner->setMaxString($defaultStringLength);
        $cloner->setMaxItems($defaultItemNumber);

        $dumper->dump($cloner->cloneVar($variable)->withMaxDepth($defaultDepth));
    }

    die(1);
}

-1 = no limit (easy to customize in this way)

So, now when you use this ddd function, you can get the complete output of normal dd function. I think this approach is better than overwriting any existing function. But be careful, since now variables with any number of depth will be displayed completely, you may experience longer loading time. Hope it helps.


0

Laravel的dd()函数用于在浏览器中打印/转储某个值,然后停止执行(跳过dd()之后给出的所有其他代码)


dd()函数的替代方案。

有两个选项。

  1. 如果您想在浏览器中打印单个值,然后停止执行。

    echo $your_value;

    exit();

  2. 如果您想在浏览器中打印一些数组值,然后停止执行。

    print_r($your_array);

    exit();


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接