Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/php/234.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Php Laravel-如何避免N+;1在刀片中加载更多结果时出现问题?_Php_Laravel - Fatal编程技术网

Php Laravel-如何避免N+;1在刀片中加载更多结果时出现问题?

Php Laravel-如何避免N+;1在刀片中加载更多结果时出现问题?,php,laravel,Php,Laravel,我正在建立一个有意见书的网站,这些意见书都有评论。这些评论的结构与reddit的非常相似。以下是一张供参考的图片: 这些评论有很多关系(auth用户是否保存了/向上投票/向下投票了评论,评论是否有子评论,谁创建了评论) 因此,为了避免大量不必要的服务器查询,我急切地加载这些关系 $comments = Comment::with(['children','owner','savedComments','votes']) ->where('submi

我正在建立一个有意见书的网站,这些意见书都有评论。这些评论的结构与reddit的非常相似。以下是一张供参考的图片:

这些评论有很多关系(auth用户是否保存了/向上投票/向下投票了评论,评论是否有子评论,谁创建了评论)

因此,为了避免大量不必要的服务器查询,我急切地加载这些关系

$comments = Comment::with(['children','owner','savedComments','votes'])
                    ->where('submission_id', $submission->id)
                    ->where('parent_id', NULL)
                    ->orderBy('removed','asc')
                    ->orderBy($sortBy, $direction)
                    ->paginate(200);
然后我在视图中输入这些注释。但是,请注意,在我的查询中,我只加载父注释

对于儿童,我通过注释的
children
关系使用
foreach
加载他们

Comment.php:

public function children() {
    return $this->hasMany('App\Comment','parent_id')->orderBy('total_score', 'desc');
}   
@foreach ($comment->children as $comment)
    @if ($loop->depth == 10)
        <div>
            <a href="{{ route('get.submission', ['subchan' => $submission->subchan, 'id' => $submission->id, 'URLtitle' => $submission->URL_title,'commentID' => $comment->parent_id]) }}">Continue this thread</a>
        </div>
        @break
    @elseif ($loop->iteration == 8 && $totalComments >= 25) 
        <div class="loadMoreReplies"
        data-submission-id="{{ $submission->id }}"
        data-parent-id="{{$comment->parent_id}}"
        >Load More Replies (<span id="remaining-reply-count-{{$comment->parent_id}}">{{ $loop->remaining + 1 }}</span>)</div>
        @break      
    @else
        <div class="comment-container comment-container-child" id="comment-container-{{$comment->id}}">
            @include('partials.comment_block')
        </div>
    @endif
@endforeach
注释\u block.blade.php:

public function children() {
    return $this->hasMany('App\Comment','parent_id')->orderBy('total_score', 'desc');
}   
@foreach ($comment->children as $comment)
    @if ($loop->depth == 10)
        <div>
            <a href="{{ route('get.submission', ['subchan' => $submission->subchan, 'id' => $submission->id, 'URLtitle' => $submission->URL_title,'commentID' => $comment->parent_id]) }}">Continue this thread</a>
        </div>
        @break
    @elseif ($loop->iteration == 8 && $totalComments >= 25) 
        <div class="loadMoreReplies"
        data-submission-id="{{ $submission->id }}"
        data-parent-id="{{$comment->parent_id}}"
        >Load More Replies (<span id="remaining-reply-count-{{$comment->parent_id}}">{{ $loop->remaining + 1 }}</span>)</div>
        @break      
    @else
        <div class="comment-container comment-container-child" id="comment-container-{{$comment->id}}">
            @include('partials.comment_block')
        </div>
    @endif
@endforeach
@foreach($comment->children as$comment)
@如果($loop->depth==10)
@中断
@elseif($loop->iteration==8&&$totalComments>=25)
加载更多回复({{$loop->剩余+1}})
@中断
@否则
@包括('partials.comment\u block')
@恩迪夫
@endforeach
问题在于,尽管父注释关系被急切加载,但每个子注释也会导致查询,因为它们是通过关系加载到视图中的。因此,我的服务器查询总数从一个增加到了数百个

我如何解决这个问题

编辑:

对于那些说我没有n+1问题的人,以下是我在不加载子注释时的查询:

这就是我加载子注释的时候:


我还使用了这个包,它肯定告诉我我有一个n+1问题。

似乎没有办法用Laravel在递归中加载嵌套关系,或者至少在这种情况下没有(尝试在多个位置询问,而不仅仅是stackoverflow)

为了解决我的问题,我将以正常方式加载所有父注释及其关系,但只加载子注释作为数据,然后用AJAX调用填充它们。这将只添加一个服务器查询

您的数据库是什么? 如果数据库支持公共表表达式,则可以将递归数据优化为单个查询。 然而,拉威尔并不支持这些。您必须创建原始查询


如果您的DB不支持CTE(公共表表达式),那么您所能做的最好的事情就是分别将每一级递归@Tim Lewis comment加载到@Felix Maxime answer,这很好地涵盖了该用例。

我可能错了,但每个子注释都不会导致新的查询,当您使用
comment::with时,查询只是一个(['children',…])
。当您在视图中执行foreach时,所有子注释都已经存在。正如@porloscerrosψ所说,您没有任何n+1问题,他们是肯定的。我在appserviceprovider中记录我的查询。我会为每个子注释获得额外的查询(在我的案例中是155)。但是如果我删除@foreach($comment->children as$comment)阻止并仅加载父注释,我的查询将下降到1。这是查询的样子:@FelixMaxime您能指出您怀疑刀片视图中的哪一行执行额外查询吗?@CaddyDZ所有子注释关系,但不包括父注释关系。添加子注释时,这是我的警报:out o出于好奇,这个问题的答案有帮助吗?这就是我在同一个模型之间实现递归性所遵循的方法,并对QOL进行了一些修改。@Timlews尝试这一方法只会给我一个ErrorException(注意事项)未定义的偏移量:0@TimLewis我确实发现了这一点:但我不理解代码嗯,不确定为什么会这样;这很复杂,但我能够从第一个链接实现解决方案。是的,我不确定第二个链接在做什么;但看起来很奇怪。ajax方法很好,如果你必须做一个ew调用以获得每一级递归,但效率相当高。