2016-03-21 18 views
2

今日、再帰を伴う無名関数に対してArrayCollection :: forAllメソッドを使用すると、私は奇妙な動作を発見しました。ArrayCollection :: forAll with recursion

前提条件:

私はPostエンティティのコレクションを持っています。各Postには、SocialPostエンティティのコレクションが含まれています。

目的: "保留" するすべてのポストと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 

は、誰もがここで問題を見ていますか?

答えて

4

のはArrayCollection source

ドキュメントを確認してみましょうは言う:何それは言っていないことは述語がfalseを返した場合ということですので、

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

これは全体の機能、forAllリターンfalseすぐをmisleasingすることができます。 のソースを見てみましょう:

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がに変換されます.の反復処理を完了する前に、forAllメソッドが中断する原因は何ですか。

ソリューションとして、あなたは時とあなたの匿名関数の行

return true; 

を追加する必要があります。

追加のノート

:コレクション内のすべての要素が条件

なく

は、各要素に対して何かをし一致した場合forAll

チェックとして理解されるべきですコレクション

これを正しく実行したい場合は、ループをforeachとするだけです。

+0

はい、あなたは正しいです。私はarray_walkとまったく同じように動作すると仮定して、このメソッドを使用していました。ありがとうございました。 – Hast