0

How can I get the comment link in a post with paged comments? Like the latest comments link that should point to a comment pagination in a post

Latest comments in homepage for example

1- link: post/1/comment-page-3/#comment-300
2- link: post/103/comment-page-2/#comment-299
3- link: post/24/comment-page-6/#comment-298
4- link: post/11/comment-page-1/#comment-297

my single post

  • article content
  • comments with pagination

my post model

 /**
 * Get all of the comments for the Posts
 *
 * @return \Illuminate\Database\Eloquent\Relations\HasMany
 */
public function comments()
{
    return $this->hasMany(Comment::class, 'post_id', 'id')
    ->whereNull('comment_parent')->where('comment_status', 1)
    ->with(['replies', 'user']);
}

public function scopeType($query, $type)
{
    return $query->wherePost_type($type);
}

my comments model

    /**
 * Get the post that owns the Comment
 *
 * @return \Illuminate\Database\Eloquent\Relations\BelongsTo
 */
public function post()
{
    return $this->belongsTo(Posts::class, 'post_id', 'id');
}


/**
 * Get all of the children for the Comment
 *
 * @return \Illuminate\Database\Eloquent\Relations\HasMany
 */
public function replies()
{
    return $this->hasMany(Comment::class, 'comment_parent', 'id')->with(['replies', 'user']);
}

my post controller

    /**
     * get and show the post
     * 
     * @param int $id requested from user
     * @param string $slug requested from user
     * @param string $page comment page requested from user
     * 
     * @return view
     */
    public function show_post($id, $post_slug = '', $comment_page_slug = '') 
    {
        
        //get post by requested id
        $post = Posts::Type('post')->with('user')->findorfail($id);

        //get post comment with paginate
        $comments = $this->get_comments_with_pagination($post, $comment_page_slug);

        //check slug request is current in db
        if ($post_slug && strtolower($post->slug) != strtolower(urlencode($post_slug)) ) 
        {
            abort(404);
        }

        //check comments working and curent paginate
        if (! $comments) {
            abort(404);
        }

        //show post with comments
        return view('site.post.show-post', ['post' => $post, 'comments' => $comments]);

    }

 /**
     * get comments and pagination url
     * 
     * @param object $post
     * 
     * @param string $page
     * 
     * @return object comments with custom paination
     */
    private function get_comments_with_pagination($post, $page) {

        //check pagination comment is current old wordpress
        $matches = array();
 
        if ($page && ! preg_match ( '/comment-page-([0-9]+)/', $page, $matches ) )
        {
            return false;
        }

        if ($matches) 
        {
            $page = $matches[1];
        }
        else 
        {
            $page = 1;
        }

        //calculate skiping comment by page number
        $skip = ($page * $this->comment_paginate) - $this->comment_paginate;

        //get comments
        $comments = $post->comments()->skip($skip)->take($this->comment_paginate)->orderBy('comment_date','desc')->get();

        //comment number
        $count = $post->comments->count();

        //create pagination template
        $page_num = round($count / $this->comment_paginate) + 1;
        $paginate_url = '';

            if ($page_num > 0 ) {
                
                for($i = 1; $i < $page_num; $i++)
                {
                    if ($i == $page) {
                        $paginate_url .= '<li class="page-numbers current"><span>'.$i.'</span></li>';
                   
                    } else {
                        
                        $paginate_url .= '<li class="page-numbers"><a href="' .route('post.show', [$post->id, $post->slug]). '/comment-page-' . $i. '/#comments">'.$i.'</a>';
             
                    }
                }

            }


        $comments->paginate = '<ul class="modami-paginate">'.$paginate_url.'</ul>';
        $comments->number = $count;

        return $comments;

    }

my view for post

<article>Post content....</article>
        
        <ol class="comments-list">
        @include('site.comments.comment-list', ['comments' => $comments])
        </ol>
       
        {!! $comments->paginate !!}

There is no problem with displaying posts and paginated comments, But now I want to show new comments with the link to the post page where that comment is in

controller for displaying latest comments ??

return Comment->where('comment_status' => 1)
        ->with('user')
        ->orderBy('comment_date', 'desc')
        ->take(10)->get();

How do I find the comment page link? I do not know how! Can help me?

1 Answers1

0

It shouldn't necessarily happen in models or query. Create link in view for new comments. According to relation find the id of comment, then create a route to show post by id. In view create html a tag with href pointing to related paginated post using route() method. Anywhere in your code , if you have the paginated comment model you can easily get the last page number by:

    $comment->lastPage()

You can check if adding new comment adds new page or not by $comments->getPerPage() , which is default perpage and $comments->count(). So if count is 20 and perpage is 10, adding new comment creates new page which is 3.

But if you don't have access to paginated comments you add this simple method to your comment model

    public function page($perPage = null)
    {
        $perPage = $perPage ?: $this->getPerPage();
        $index = self::where('post_id', $this->post_id)->where('id', '<', $this->id)->count();
        $page = (int) ($index / $perPage) + 1;
        return route('post.show', ['post' => $this->post_id, 'page' => $page]);
    }

now any comment model has link to post page , where comments are paginated to the comment model

<a href="{{$comment->page()}}">SHOW COMMENT IN POST</a>

EDIT

Keep in mind that paginator works with offset and limit. So you just need to know where your record is located on model. If you have 25 records and you want to go to a page where 17th comment is on it, and your perpage is 10, link created by below will do the job:

   route('post.index',['page'=>2]);

It is assumed you haven't changed the $pageName of paginate method on model query.

MHIdea
  • 806
  • 3
  • 8
  • I can find the post link by route() and post id. But post comments are paginated. How do I find the comment page in the post? – shahriyar.m May 13 '21 at 17:21
  • For example, a person replies to a comment on page 7 of post with pagination comments. This reply is shown as the latest comment. Now, by clicking on it, should refer to page 7 of that post. Because post comments are paginated – shahriyar.m May 13 '21 at 17:33
  • I found the answer in this link(https://stackoverflow.com/a/29155685/5149704). But it is not good performance and I am still looking for a better solution – shahriyar.m May 13 '21 at 19:46
  • First I need to find the number of comments before the current comment (one extra query for each comment). Then i need divide this number by number of pagination. The number obtained is the current comment page. its not good but i try this – shahriyar.m May 13 '21 at 20:11
  • No no no. you dont' need to do extra query. If you only need tha last one it's easy to get. check https://laravel.com/docs/8.x/pagination#paginator-instance-methods – MHIdea May 13 '21 at 20:16
  • Can you give an example? Posts with paginated comments, Show the latest comments on the home page and create comment links Each comment on the home page may be on page 5 or 10 or ... in post with pagination comments. By clicking on the comment link in home page, you should be taken to the comment page in the post – shahriyar.m May 13 '21 at 22:43
  • Ok, sure. But would you please accept the answer if it has been helpful so far? – MHIdea May 14 '21 at 03:18
  • Yes. I'll do. The answer above is not my answer, but your example or changes can be my answer and helpful. – shahriyar.m May 14 '21 at 08:13
  • 1
    extra query per comment in loop. $this->post->comments->where('id', '<', $this->id)->count(); thank you. This is my problem, but I do not know if this solution best performance – shahriyar.m May 14 '21 at 10:14
  • check update. Sorry for performance issue. we don't need to retrieve post model in page method. But notice that you can't find index of a comment in post's comments unless you do a query. it's unavoidable. As I said earlier in case you have the post model , by either paginator methods or comments collection methods, you don't need extra query. – MHIdea May 14 '21 at 11:09