2010-12-03 14 views
5

Zend_View_Helper_Navigation_Menu genişletilmiş ve menü ağacı üzerinde yinelemek için bir RecursiveIteratorIterator kullanır. Benim belirleyebileceğim şey, ağaçtaki bir dal seviyesi için ilk veya son öğede olduğumdur. İşte PHP RecursiveIteratorIterator: Her bir şube düzeyinde ilk ve son öğeyi belirleme

bir örnek ben aradığım:

  • Nav 1 (ilk)
    • Nav 1.1 (son ilk &)
      • Nav 1.1.1 (ilk)
      • Nav 1.1.2
      • Nav 1.1.3 (son)
  • Gezinme 2
    • Gezinme 2.1 (ilk)
    • Gezinme 2.2 (son)
  • Gezinme 3 (son)
    • Gezinme 3.1 (ilk)
    • Gezinme 3.2 (son)

Ek Bilgiler

  • PHP Sürümü 5.2.13

Çözüm iki değişken takip etmek için kullanılabilecek foreach ($iterator as $page) döngü içinde

derinlikler, $depth ve $prevDepth. Basit bir karşılaştırma koşulu, daha sonra bir dal seviyesinde ilk maddeyi belirleyebilir: if ($depth > $prevDepth).

Zend_Navigation_Container nesne kullanılarak RecursiveCachingIterator oluşturma ve daha sonra bu RecursiveIteratorIteratorhasNext() yöntemi ekler oluşturmak için kullanılmıştır.

$rci = new RecursiveCachingIterator($container, CachingIterator::FULL_CACHE); 
$iterator = new RecursiveIteratorIterator($rci, 
        RecursiveIteratorIterator::SELF_FIRST); 
/* snip */ 
$prevDepth = -1; 
foreach ($iterator as $page) { 
    $depth = $iterator->getDepth(); 
    /* snip */ 
    if ($depth > $prevDepth) { 
     // first branch item 
    } 
    /* snip */ 
    if (!$iterator->hasNext()) { 
     // last branch item 
    } 
    /* snip */ 
    $prevDepth = $depth; 
} 
+0

Bir şekilde 'getChildren' veya' nextElement' kullanılarak mümkün olmalıdır ... Ancak ne yazık ki, bu sınıflar henüz belgelenmiş değil http://www.php.net/manual/en/class.recursiveiteratoriterator.php –

+0

Ne mod, "RecursiveIteratorIterator" ile çalışıyor (kurucunun ikinci parametresidir)? "LEAVES_ONLY", "CHILD_FIRST" veya "SELF_FIRST" ("LEAVES_ONLY" varsayılan)? – ircmaxell

+0

nasıl kullanacağınızı nasıl kullanacağınıza dair bir örnek verebilir misiniz – Gordon

cevap

3

kullanma RecursiveCachingIterator: dizisi ile

$rdi = new RecursiveDirectoryIterator('.'); 
$rci = new RecursiveCachingIterator($rdi, CachingIterator::FULL_CACHE); 
$rii = new RecursiveIteratorIterator($rci, RecursiveIteratorIterator::SELF_FIRST); 

foreach ($rii as $file) { 
    if ($file->isDir()) { 
     echo $file->getFilename() . PHP_EOL; 
    } 
    elseif (!$rii->hasNext()) { 
     echo $file->getFilename() . PHP_EOL; 
    } 
    elseif (count($rii->getCache()) == 1) { 
     echo $file->getFilename() . PHP_EOL; 
    } 
} 

Başka bir çözüm: $ yineleyici yoğun dizidir

function buildTree(RecursiveDirectoryIterator $iterator) { 
    $tree = array(); 
    foreach ($iterator as $fileinfo) { 
     if ($fileinfo->isDir()) { 
      $tree[$fileinfo->getFilename()] = buildTree($iterator->getChildren()); 
     } else { 
      $tree[$fileinfo->getFilename()] = $fileinfo->getFilename(); 
     } 
    } 
    return $tree; 
} 

function filterTree(array $tree) { 
    foreach ($tree as $key => $value) { 
     if (is_array($value)) { 
      $tree[$key] = filterTree($value); 
     } elseif (reset($tree) !== $value && end($tree) !== $value) { 
      unset($tree[$key]); 
     } 
    } 
    return $tree; 
} 

print_r(filterTree(buildTree(new RecursiveDirectoryIterator('.')))); 
+0

Burada bazı güzel kod örnekleri yayınladınız, ancak ilk veya son öğeyi nerede belirlediğinizi göremiyorum. – Sonny

+0

@Sonny: İlk snippet'te $ rii-> hasNext() ', son öğe ve sayım ($ rii-> getCache())' dır, ancak yineleyici ilk öğe üzerindeyse, 1'e eşittir. İkinci snippet'te sıfırla ($ tree)! == $ value && end ($ tree)! == $ value', ilk ve son elemanlar hariç hepsi için geçerlidir. – rik

+0

Açıklamanıza bağlı olarak, sadece "düzleştirilmiş" yineleyicinin ilk ve son elemanını belirlediği gibi, dal/seviyenin ilk ve son öğelerini değil gibi görünür. Adil olmak gerekirse, asıl sorum bu açıklığa kavuşmamış olabilir, bu yüzden bunu açıklığa kavuşturmak için güncelledim. – Sonny

0

, bu işe yarayabilecek:

// iterate container 
$prevDepth = -1; 
foreach ($iterator as $key => $page) { 
    $depth = $iterator->getDepth(); 
    /* snip */ 
    if ($depth > $prevDepth) { 
     // $page is first branch item 

     if (isset($iterator[$key - 1])) { 
      // $iterator[$key - 1] is last branch item in previous branch 
     } 
    } 
    /* snip */ 
    $prevDepth = $depth; 
} 

Göreceksin çok test etmek zorunda son madde ayrı ayrı.

İlgili konular