0

我们有两个模型。电子书 HABTM 标签,其中标签遵循​​树的行为。

对于每个标签,我们需要两个数字。首先,与标签关联的电子书数量,其次是与标签关联的电子书数量 + 每个后代关联的电子书数量。

我们如何在树格式的数组中获取带有这些数字的标签?

非常感谢您的帮助。

更新:有一个日期时间参数 Ebook.published 定义了何时计算书籍。应该计算所有具有 codeEbook.published < NOW() 的电子书。

4

2 回答 2

1

Cake 对此没有基本的支持。您将需要即时进行计算或使用自定义代码创建自己的计数器缓存以进行更新。这很乱。

我建议在您的电子书控制器中覆盖 beforeSave() 和 afterSave() 函数。如果更新,请在 beforeSave() 中获取与电子书关联的当前现有标签集。在 afterSave() 中抓取新的标签集并将其与前一组标签合并。如果有任何更改,请遍历所有标签并调用$this->Tag->getPath($id)以获取所有祖先的列表。您现在将拥有受保存影响的所有标签。您现在可以遍历它们并更新计数。

于 2011-04-25T22:19:44.820 回答
0

实际上,我找到了一个更简单的解决方案,因为我已经构建了返回标签树的函数。我对每个标签使用了一个查询来获取那一刻的实际计数。这是我建立的。随意根据您的需要使用它。

在标签模型中

// Returns the number of published ebooks of selected tag
function count_direct_published($tag_id = 0){
    $temp = $this->query('SELECT count(*) as count FROM ebooks_tags LEFT JOIN ebooks ON ebooks_tags.ebook_id = ebooks.id WHERE ebooks.published < NOW() AND ebooks_tags.tag_id = '.$tag_id);
    return $temp[0][0]['count'];
}


// Returns an array in tree format with $id tag and all his children
// $id = 0 start from the top (parent_id = null), or, from $id = the top's tag id
// $limit = boolean (default false)
// $level = Is the limit of depth applied only if $limit = true
// $ext = true Means this is the first time the function is called
// You can run tree_builder(), returns all the tree,
function tree_builder($id = 0, $limit = false, $level = 1, $ext = 1){
    if($ext == 1){
        $ext = 0;
        $undo = true; 
    }else{
        $undo = false;
    }
$this->recursive=-1;

    $this->contain('EbooksTag');

    $var = array();
    $count_all = 0;
    // If limit = too big , exit
    if($limit !== false && $level > $limit){
        return '';
    }
    // Or else, 
    // If $id=0, find all the children
    if($id == 0){
        $tags = $this->find('all',array('conditions'=>array( 'Tag.parent_id IS NULL'), 'order'=>array('Tag.gre')));
    // If $id!=0 && runs internally
    }elseif($id != 0 && !$undo ){
        $tags = $this->find('all',array('conditions'=>array( 'Tag.parent_id'=>$id ), 'order'=>array('Tag.gre')));
    }
    // If $id!=0 && is called from outside 
    elseif($id != 0 && $undo){
        $tags = $this->find('all',array('conditions'=>array( 'Tag.id'=>$id )));

    }

    foreach($tags as $key => $tag){
        $var[] = $tag;
        $next = $this->tree_builder($tag['Tag']['id'], $limit, $level+1, $ext);
        end($var); // move the internal pointer to the end of the array
        $last_key = key($var); // fetches the key of the element pointed to by the internal pointer
        $var[$last_key]['children'] = $next['var'];
        $counter_direct = $this->count_direct_published($id);
        $var[$last_key]['Tag']['count_all'] = $next['count_all']+$counter_direct;
        $count_all += $var[$last_key]['Tag']['count_all'];

    }

    if( $undo )
    {
        return $var;
    }else{
        return array('count_all'=> $count_all, 'var' => $var);
    }

}

在 tags_controller.php

$this->set('tags', $this->Tag->tree_builder());

在视图中

<?php foreach($tags as $tag){?>
    <?php // Ο Γονέας σε dropdown box ?>
    <div class="main-categ">
    <?php echo $tag['Tag']['gre']; ?>
    <?php echo $html->image('layout/arrows.png', array('alt'=> "Expand")); ?>
    </div>



    <div class="collapse"> 
        <?php // Τα στοιχεία του γονέα ?>
        <div class="tag-1">
            <span class="tag-1">
                <?php // Αν ?>
                <?php if($tag['Tag']['count_direct']>0){
                    // Display link
                     echo $html->link($tag['Tag']['gre'],array('action'=>'view',$tag['Tag']['id']));
                     echo ' ('.$tag['Tag']['count_direct'].')';
                }else{
                    // Display text
                     echo $tag['Tag']['gre'];

                }  ?>
            </span> 
            &nbsp;&nbsp;&nbsp;&nbsp;
            <?php echo $html->link( 'view all' ,array('action'=>'view_all',$tag['Tag']['id'])); ?>
             (<?php echo $tag['Tag']['count_all']; ?>)
        </div>  

        <?php // Για κάθε πρώτο παιδί ?>
        <?php foreach($tag['children'] as $tag_1){ ?>
        <div>
            <span class="tag-2">
                <?php if($tag_1['Tag']['count_direct']>0){
                    // Display link
                     echo $html->link($tag_1['Tag']['gre'],array('action'=>'view',$tag_1['Tag']['id']));
                     echo ' ('.$tag_1['Tag']['count_direct'].')';
                }else{
                    // Display text
                     echo $tag_1['Tag']['gre'];

                }  ?>
            </span>
            &nbsp;&nbsp;&nbsp;&nbsp; 
            <?php echo $html->link( 'view all' ,array('action'=>'view_all',$tag_1['Tag']['id'])); ?>
             (<?php echo $tag_1['Tag']['count_all']; ?>)

                <?php // Τα δεύτερα παιδιά ?>
                <?php $i=0; ?>
                <?php foreach($tag_1['children'] as $tag_2){ ?>
                    <?php if($i==0){ echo '<ul class="split">'; $i++; } ?>
                    <li>
                    <?php if($tag_2['Tag']['count_direct']>0){
                            // Display link
                             echo $html->link($tag_2['Tag']['gre'],array('action'=>'view',$tag_2['Tag']['id']));
                             echo ' ('.$tag_2['Tag']['count_direct'].')';
                        }else{
                            // Display text
                             echo $tag_2['Tag']['gre'];

                        }  ?>                       
                    </li>
                <?php } ?>
                <?php if($i==1) echo '</ul>'; ?>

            <div class="clear"></div>       
        </div>

        <?php } ?>      

    </div>

也许它不是最好的解决方案,但它确实有效。希望有帮助

于 2011-04-27T13:49:11.530 回答