【问题标题】:ArrayCollection::forAll with recursionArrayCollection::forAll 递归
【发布时间】:2016-07-08 13:05:20
【问题描述】:

今天我发现在对带有递归的匿名函数使用 ArrayCollection::forAll 方法时出现了奇怪的行为。

前提条件:

我有一组Post 实体。每个Post 都包含SocialPost 实体的集合。

目标

将所有 Post 和 SocialPost 实体的状态设置为“待处理”。

我的解决方案:

我认为我可以使用非常简单的闭包,如下所示:

    $setPending = function($_, StatusAwareInterface $post) use (&$setPending) {
        echo "func entry point reached\r\n";
        if ($post instanceof Post) {
            echo "This is post. SP Count: " . count($post->getSocialPosts()) . "\r\n";
            $post->getSocialPosts()->forAll($setPending);
            $status = Post::STATUS_PENDING;
        } else {
            echo "This is SP\r\n";
            $status = SocialPost::STATUS_PENDING;
        }

        $post->setStatus($status);
    };

    // $post contains 2 Post entities
    // Each Post entity contains 50+ SocialPost entities
    $posts->forAll($setPending);

结果:

但是输出很奇怪。看起来 forAll 只使用了第一项然后中断:

func entry point reached
This is post. SP Count: 52
func entry point reached
This is SP

有人看到这里的问题吗?

【问题讨论】:

    标签: php symfony recursion doctrine closures


    【解决方案1】:

    我们来看看 ArrayCollection source

    文档说:

          * Applies the given predicate p to all elements of this collection,
          * returning true, if the predicate yields true for all elements.
    

    这可能是误导,因为它没有说如果谓词返回false,则整个函数forAll 返回false立即。 我们来看看源码:

    public function forAll(Closure $p)
    {
        foreach ($this->elements as $key => $element) {
            if ( ! $p($key, $element)) { // <-- here's null converted to false.
                return false;
            }
        }
    
        return true;
    }
    

    您的函数不返回任何内容,即null。更进一步,null 被转换为false,导致forAll 方法在完成对ArrayCollection 的迭代之前中断。

    作为解决方案,您应该添加行

    return true;
    

    在你的匿名函数中。

    补充说明forAll应该理解为

    检查集合中的每个元素是否都符合条件

    而不是

    为集合的每个元素做一些事情

    如果你想做到这一点,你应该简单地做foreach循环。

    【讨论】:

    • 是的,你是对的。我正在使用这种方法,假设它的工作原理与 array_walk 完全一样。谢谢。
    猜你喜欢
    • 1970-01-01
    • 2012-08-14
    • 1970-01-01
    • 2010-11-14
    • 1970-01-01
    • 1970-01-01
    • 2017-11-11
    • 1970-01-01
    • 2011-12-25
    相关资源
    最近更新 更多