Laravel嵌套儿童计数(类别)

时间:2018-11-07 20:50:29

标签: php laravel eloquent adjacency-list

我在Laravel网站上使用嵌套类别,并使用了一个nextcy列表样式的mysql表布局。最多有7层分类(使用google categories taxonomy)。请查看下面的图像以获取一小部分数据示例,以及下面的代码以了解我的类别模型的关系。

每个类别都有零到许多子类别(使用相同的类别模型),并且在其下零到许多页面。 我的目标是找到一种方法来统计类别下的所有页面(包括其子类别下的页面)。

MySql Table Layout Example

我的类别模型具有以下所有可正常运行的关系:

classified_text = [[('John', 'PERSON'), ('Smith', 'PERSON')], 
                   [('University', 'ORGANIZATION'), ('of', 'ORGANIZATION'), ('ABC', 'ORGANIZATION')],
                   [('some', 'O'), ('text', 'O'), ('here', 'O')],
                   [('Mark', 'O'), ('from', 'O'), ('University', 'ORGANIZATION'), ('of', 'ORGANIZATION'), ('CA', 'ORGANIZATION')]]

newlist = []
for sublist in classified_text:
    combined = []
    for chunk, tag in sublist:
        if tag == 'O':
            continue
        combined_tag = tag
        combined.append(chunk)

    # Append tag and string to list
    if combined:
        # If you wanted to space filled as in your example, you can use
        # the strings ljust method
        newlist.append((combined_tag.ljust(12), ' '.join(combined)))

print(newlist)

#[('PERSON      ', 'John Smith'),
# ('ORGANIZATION', 'University of ABC'),
# ('ORGANIZATION', 'University of CA')]

2 个答案:

答案 0 :(得分:1)

这不是我使用关系的方式,但是偷偷摸摸的方式是:

public function childCount(){
  return DB::table('categories')->where('slug', 'LIKE', $this->slug . '%')->count() - 1;
}

要获取页面,也许:

public function pageCount(){
  return Page::whereIn('category_id', 
     DB::table('categories')->select('id')->where('slug', 'LIKE', $this->slug . '%')->get()->pluck('id')
  )->count();
}

2个查询可能会进行优化,但可以正常工作

答案 1 :(得分:1)

因为我渴望使用以下代码行和我的Categories模型在第一部分中加载所有这些类别和页面:

$categories = Category::with( 'childrenRecursive' )->whereNull( 'parent_id' )->get();

我能够使用递归公式来汇总每个类别下的页面数,而不会降低页面速度:

foreach( $categories as $category ) {
    $category->pagesCount = 0;
    $category->pagesCount += $category->pages->count();
    foreach( $category->childrenRecursive as $child ) {
        $category->pagesCount += countChildPages( $child );
    }
}

function countChildPages( $category ) {
    $category->pagesCount = 0;
    $category->pagesCount += $category->pages->count();
    foreach( $category->childrenRecursive as $child ) {
        $category->pagesCount += countChildPages( $child );
    }
    return $category->pagesCount;
}

然后,每当需要在页面上使用计数时,我就可以访问该计数($ category-> pagesCount)。




示例的sitemap.html页面:

foreach( $categories as $category ) {
    $category->pagesCount = 0;
    $category->pagesCount += $category->pages->count();
    foreach( $category->childrenRecursive as $child ) {
        $category->pagesCount += countChildPages( $child );
    }
}

foreach( $categories as $category ) {
    if( $category->pagesCount > 0 ) {
        echo '<div class="category">';
            echo '<h2><a href="https://example.com/' . $category->slug . '">' . $category->name . ' (' . $category->pagesCount . ')</a></h2>';
            foreach( $category->pages as $page ) {
                showPage( $page );
            }
            foreach( $category->childrenRecursive as $child ) {
                showSubCategory( $child );
            }
        echo '</div>';
    }
}

function countChildPages( $category ) {
    $category->pagesCount = 0;
    $category->pagesCount += $category->pages->count();
    foreach( $category->childrenRecursive as $child ) {
        $category->pagesCount += countChildPages( $child );
    }
    return $category->pagesCount;
}

function showSubCategory( $category ) {
    if( $category->pagesCount > 0 ) {
        echo '<div class="category">';
            echo '<h2><a href="https://example.com/' . $category->slug . '">' . $category->name . ' (' . $category->pagesCount . ')</a></h2>';
            foreach( $category->pages as $page ) {
                showPage( $page );
            }
            foreach( $category->childrenRecursive as $child ) {
                showSubCategory( $child );
            }
        echo '</div>';
    }
}

function showPage( $page ) {
    echo '<div class="category page">';
        echo '<h2><a href="https://example.com/' . $page->slug . '">' . $page->title . '</a></h2>';
    echo '</div>';
}